gnunet-svn
[Top][All Lists]
Advanced

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

[taler-wallet-core] branch master updated: adding auditor-backoffice-ui


From: gnunet
Subject: [taler-wallet-core] branch master updated: adding auditor-backoffice-ui
Date: Sun, 14 Jan 2024 15:20:54 +0100

This is an automated email from the git hooks/post-receive script.

nic-eigel pushed a commit to branch master
in repository wallet-core.

The following commit(s) were added to refs/heads/master by this push:
     new 7a201c3b8 adding auditor-backoffice-ui
7a201c3b8 is described below

commit 7a201c3b885c5d23bf0fd0f3da32379a49b30c38
Author: Nic Eigel <nic@eigel.ch>
AuthorDate: Sun Jan 14 15:18:12 2024 +0100

    adding auditor-backoffice-ui
---
 packages/aml-backoffice-ui/src/context/config.ts   |     3 +-
 packages/auditor-backoffice-ui/.gitignore          |     6 +
 packages/auditor-backoffice-ui/DESIGN.md           |   195 +
 packages/auditor-backoffice-ui/Makefile            |    35 +
 packages/auditor-backoffice-ui/README.md           |    64 +
 packages/auditor-backoffice-ui/build.mjs           |    28 +
 packages/auditor-backoffice-ui/contrib/po2ts       |    42 +
 packages/auditor-backoffice-ui/copyleft-header.js  |    15 +
 packages/auditor-backoffice-ui/dev.mjs             |    40 +
 packages/auditor-backoffice-ui/package.json        |    83 +
 packages/auditor-backoffice-ui/preact.config.js    |    70 +
 .../auditor-backoffice-ui/preact.single-config.js  |    62 +
 .../remove-link-stylesheet.sh                      |     8 +
 packages/auditor-backoffice-ui/src/AdminRoutes.tsx |    53 +
 packages/auditor-backoffice-ui/src/Application.tsx |   165 +
 .../src/ApplicationReadyRoutes.tsx                 |   175 +
 .../auditor-backoffice-ui/src/InstanceRoutes.tsx   |   800 +
 .../auditor-backoffice-ui/src/assets/empty.png     |   Bin 0 -> 2785 bytes
 .../src/assets/icons/android-chrome-192x192.png    |   Bin 0 -> 14058 bytes
 .../src/assets/icons/android-chrome-512x512.png    |   Bin 0 -> 51484 bytes
 .../src/assets/icons/apple-touch-icon.png          |   Bin 0 -> 12746 bytes
 .../src/assets/icons/favicon-16x16.png             |   Bin 0 -> 626 bytes
 .../src/assets/icons/favicon-32x32.png             |   Bin 0 -> 1487 bytes
 .../src/assets/icons/languageicon.svg              |    48 +
 .../src/assets/icons/mstile-150x150.png            |   Bin 0 -> 9050 bytes
 .../auditor-backoffice-ui/src/assets/logo-2021.svg |     9 +
 .../auditor-backoffice-ui/src/assets/logo.jpeg     |   Bin 0 -> 39336 bytes
 .../src/components/exception/AsyncButton.tsx       |    55 +
 .../src/components/exception/QR.tsx                |    49 +
 .../src/components/exception/loading.tsx           |    48 +
 .../src/components/form/FormProvider.tsx           |   109 +
 .../src/components/form/Input.tsx                  |   116 +
 .../src/components/form/InputArray.tsx             |   139 +
 .../src/components/form/InputBoolean.tsx           |    91 +
 .../src/components/form/InputCurrency.tsx          |    67 +
 .../src/components/form/InputDate.tsx              |   164 +
 .../src/components/form/InputDuration.tsx          |   186 +
 .../src/components/form/InputGroup.tsx             |    86 +
 .../src/components/form/InputImage.tsx             |   122 +
 .../src/components/form/InputLocation.tsx          |    53 +
 .../src/components/form/InputNumber.tsx            |    60 +
 .../src/components/form/InputPayto.tsx             |    52 +
 .../src/components/form/InputPaytoForm.stories.tsx |    47 +
 .../src/components/form/InputPaytoForm.tsx         |   397 +
 .../src/components/form/InputSearchOnList.tsx      |   204 +
 .../src/components/form/InputSecured.stories.tsx   |    61 +
 .../src/components/form/InputSecured.tsx           |   186 +
 .../src/components/form/InputSelector.tsx          |    94 +
 .../src/components/form/InputStock.stories.tsx     |   162 +
 .../src/components/form/InputStock.tsx             |   224 +
 .../src/components/form/InputTab.tsx               |    90 +
 .../src/components/form/InputTaxes.tsx             |   147 +
 .../src/components/form/InputToggle.tsx            |    91 +
 .../src/components/form/InputWithAddon.tsx         |   116 +
 .../src/components/form/JumpToElementById.tsx      |    59 +
 .../src/components/form/TextField.tsx              |    71 +
 .../src/components/form/useField.tsx               |    92 +
 .../src/components/form/useGroupField.tsx          |    41 +
 .../src/components/index.stories.ts                |    17 +
 .../instance/DefaultInstanceFormFields.tsx         |   124 +
 .../src/components/menu/LangSelector.tsx           |    92 +
 .../src/components/menu/NavigationBar.tsx          |    72 +
 .../src/components/menu/SideBar.tsx                |   284 +
 .../src/components/menu/index.tsx                  |   269 +
 .../src/components/modal/index.tsx                 |   496 +
 .../notifications/CreatedSuccessfully.tsx          |    57 +
 .../notifications/Notifications.stories.tsx        |    62 +
 .../src/components/notifications/index.tsx         |    65 +
 .../src/components/picker/DatePicker.tsx           |   349 +
 .../components/picker/DurationPicker.stories.tsx   |    55 +
 .../src/components/picker/DurationPicker.tsx       |   211 +
 .../product/InventoryProductForm.stories.tsx       |    62 +
 .../components/product/InventoryProductForm.tsx    |   127 +
 .../components/product/NonInventoryProductForm.tsx |   215 +
 .../src/components/product/ProductForm.tsx         |   178 +
 .../src/components/product/ProductList.tsx         |   106 +
 .../src/context/backend.test.ts                    |   163 +
 .../auditor-backoffice-ui/src/context/backend.ts   |    69 +
 .../auditor-backoffice-ui/src/context/config.ts    |    32 +
 .../auditor-backoffice-ui/src/context/instance.ts  |    36 +
 packages/auditor-backoffice-ui/src/custom.d.ts     |    42 +
 .../auditor-backoffice-ui/src/declaration.d.ts     |  1830 +++
 packages/auditor-backoffice-ui/src/hooks/async.ts  |    77 +
 .../auditor-backoffice-ui/src/hooks/backend.ts     |   477 +
 packages/auditor-backoffice-ui/src/hooks/bank.ts   |   217 +
 .../src/hooks/deposit_confirmations.ts             |   161 +
 packages/auditor-backoffice-ui/src/hooks/index.ts  |   151 +
 .../src/hooks/instance.test.ts                     |   741 +
 .../auditor-backoffice-ui/src/hooks/instance.ts    |   313 +
 .../auditor-backoffice-ui/src/hooks/listener.ts    |    85 +
 .../src/hooks/notifications.ts                     |    56 +
 .../auditor-backoffice-ui/src/hooks/order.test.ts  |   587 +
 packages/auditor-backoffice-ui/src/hooks/order.ts  |   289 +
 packages/auditor-backoffice-ui/src/hooks/otp.ts    |   223 +
 .../src/hooks/product.test.ts                      |   362 +
 .../auditor-backoffice-ui/src/hooks/product.ts     |   177 +
 .../src/hooks/reserve.test.ts                      |   448 +
 .../auditor-backoffice-ui/src/hooks/reserves.ts    |   181 +
 .../auditor-backoffice-ui/src/hooks/templates.ts   |   266 +
 .../auditor-backoffice-ui/src/hooks/testing.tsx    |   180 +
 .../src/hooks/transfer.test.ts                     |   254 +
 .../auditor-backoffice-ui/src/hooks/transfer.ts    |   188 +
 packages/auditor-backoffice-ui/src/hooks/urls.ts   |   303 +
 .../auditor-backoffice-ui/src/hooks/useSettings.ts |    73 +
 .../auditor-backoffice-ui/src/hooks/webhooks.ts    |   178 +
 packages/auditor-backoffice-ui/src/i18n/de.po      |  2742 ++++
 packages/auditor-backoffice-ui/src/i18n/en.po      |  2741 ++++
 packages/auditor-backoffice-ui/src/i18n/es.po      |  2854 ++++
 packages/auditor-backoffice-ui/src/i18n/fr.po      |  2741 ++++
 packages/auditor-backoffice-ui/src/i18n/it.po      |  2742 ++++
 packages/auditor-backoffice-ui/src/i18n/poheader   |    27 +
 .../auditor-backoffice-ui/src/i18n/strings-prelude |    19 +
 packages/auditor-backoffice-ui/src/i18n/strings.ts |  9655 ++++++++++++
 packages/auditor-backoffice-ui/src/i18n/sv.po      |  2741 ++++
 .../src/i18n/taler-merchant-backoffice.pot         |  2726 ++++
 packages/auditor-backoffice-ui/src/index.html      |    45 +
 packages/auditor-backoffice-ui/src/index.tsx       |    24 +
 .../src/paths/admin/create/Create.stories.tsx      |    57 +
 .../src/paths/admin/create/CreatePage.tsx          |   257 +
 .../admin/create/InstanceCreatedSuccessfully.tsx   |    74 +
 .../src/paths/admin/create/index.tsx               |    82 +
 .../src/paths/admin/create/stories.tsx             |    52 +
 .../src/paths/admin/index.stories.ts               |    18 +
 .../src/paths/admin/list/TableActive.tsx           |   287 +
 .../src/paths/admin/list/View.stories.tsx          |    90 +
 .../src/paths/admin/list/View.tsx                  |   110 +
 .../src/paths/admin/list/index.tsx                 |   140 +
 .../instance/accounts/create/Create.stories.tsx    |    28 +
 .../paths/instance/accounts/create/CreatePage.tsx  |   173 +
 .../src/paths/instance/accounts/create/index.tsx   |    65 +
 .../paths/instance/accounts/list/List.stories.tsx  |    28 +
 .../src/paths/instance/accounts/list/ListPage.tsx  |    64 +
 .../src/paths/instance/accounts/list/Table.tsx     |   385 +
 .../src/paths/instance/accounts/list/index.tsx     |   107 +
 .../instance/accounts/update/Update.stories.tsx    |    32 +
 .../paths/instance/accounts/update/UpdatePage.tsx  |   195 +
 .../src/paths/instance/accounts/update/index.tsx   |    96 +
 .../create/Create.stories.tsx                      |    43 +
 .../deposit_confirmations/create/CreatePage.tsx    |    80 +
 .../create/CreatedSuccessfully.tsx                 |    72 +
 .../deposit_confirmations/create/index.tsx         |    60 +
 .../deposit_confirmations/list/List.stories.tsx    |    61 +
 .../instance/deposit_confirmations/list/Table.tsx  |   496 +
 .../instance/deposit_confirmations/list/index.tsx  |   151 +
 .../update/Update.stories.tsx                      |    73 +
 .../deposit_confirmations/update/UpdatePage.tsx    |    99 +
 .../deposit_confirmations/update/index.tsx         |    95 +
 .../src/paths/instance/details/DetailPage.tsx      |    83 +
 .../src/paths/instance/details/index.tsx           |    87 +
 .../src/paths/instance/details/stories.tsx         |    68 +
 .../src/paths/instance/index.stories.ts            |    19 +
 .../paths/instance/kyc/list/ListPage.stories.tsx   |    58 +
 .../src/paths/instance/kyc/list/ListPage.tsx       |   208 +
 .../src/paths/instance/kyc/list/index.tsx          |    63 +
 .../instance/orders/create/Create.stories.tsx      |    71 +
 .../paths/instance/orders/create/CreatePage.tsx    |   705 +
 .../orders/create/OrderCreatedSuccessfully.tsx     |   114 +
 .../src/paths/instance/orders/create/index.tsx     |   114 +
 .../instance/orders/details/Detail.stories.tsx     |   135 +
 .../paths/instance/orders/details/DetailPage.tsx   |   770 +
 .../src/paths/instance/orders/details/Timeline.tsx |   129 +
 .../src/paths/instance/orders/details/index.tsx    |    95 +
 .../paths/instance/orders/list/List.stories.tsx    |   107 +
 .../src/paths/instance/orders/list/ListPage.tsx    |   226 +
 .../src/paths/instance/orders/list/Table.tsx       |   417 +
 .../src/paths/instance/orders/list/index.tsx       |   231 +
 .../instance/otp_devices/create/Create.stories.tsx |    28 +
 .../instance/otp_devices/create/CreatePage.tsx     |   180 +
 .../otp_devices/create/CreatedSuccessfully.tsx     |   104 +
 .../paths/instance/otp_devices/create/index.tsx    |    70 +
 .../instance/otp_devices/list/List.stories.tsx     |    28 +
 .../paths/instance/otp_devices/list/ListPage.tsx   |    64 +
 .../src/paths/instance/otp_devices/list/Table.tsx  |   211 +
 .../src/paths/instance/otp_devices/list/index.tsx  |   106 +
 .../instance/otp_devices/update/Update.stories.tsx |    32 +
 .../instance/otp_devices/update/UpdatePage.tsx     |   171 +
 .../paths/instance/otp_devices/update/index.tsx    |   102 +
 .../instance/products/create/Create.stories.tsx    |    43 +
 .../paths/instance/products/create/CreatePage.tsx  |    80 +
 .../products/create/CreatedSuccessfully.tsx        |    72 +
 .../src/paths/instance/products/create/index.tsx   |    60 +
 .../paths/instance/products/list/List.stories.tsx  |    61 +
 .../src/paths/instance/products/list/Table.tsx     |   496 +
 .../src/paths/instance/products/list/index.tsx     |   150 +
 .../instance/products/update/Update.stories.tsx    |    73 +
 .../paths/instance/products/update/UpdatePage.tsx  |    99 +
 .../src/paths/instance/products/update/index.tsx   |    95 +
 .../instance/reserves/create/Create.stories.tsx    |    43 +
 .../paths/instance/reserves/create/CreatePage.tsx  |   277 +
 .../create/CreatedSuccessfully.stories.tsx         |   120 +
 .../reserves/create/CreatedSuccessfully.tsx        |   190 +
 .../src/paths/instance/reserves/create/index.tsx   |    71 +
 .../paths/instance/reserves/details/DetailPage.tsx |   266 +
 .../instance/reserves/details/Details.stories.tsx  |   126 +
 .../paths/instance/reserves/details/RewardInfo.tsx |    88 +
 .../src/paths/instance/reserves/details/index.tsx  |    68 +
 .../instance/reserves/list/AutorizeRewardModal.tsx |   124 +
 .../instance/reserves/list/CreatedSuccessfully.tsx |   102 +
 .../paths/instance/reserves/list/List.stories.tsx  |    96 +
 .../src/paths/instance/reserves/list/Table.tsx     |   320 +
 .../src/paths/instance/reserves/list/index.tsx     |   171 +
 .../instance/templates/create/Create.stories.tsx   |    28 +
 .../paths/instance/templates/create/CreatePage.tsx |   259 +
 .../src/paths/instance/templates/create/index.tsx  |    61 +
 .../paths/instance/templates/list/List.stories.tsx |    28 +
 .../src/paths/instance/templates/list/ListPage.tsx |    68 +
 .../src/paths/instance/templates/list/Table.tsx    |   235 +
 .../src/paths/instance/templates/list/index.tsx    |   152 +
 .../src/paths/instance/templates/qr/Qr.stories.tsx |    27 +
 .../src/paths/instance/templates/qr/QrPage.tsx     |   172 +
 .../src/paths/instance/templates/qr/index.tsx      |    80 +
 .../instance/templates/update/Update.stories.tsx   |    32 +
 .../paths/instance/templates/update/UpdatePage.tsx |   254 +
 .../src/paths/instance/templates/update/index.tsx  |    99 +
 .../paths/instance/templates/use/Use.stories.tsx   |    27 +
 .../src/paths/instance/templates/use/UsePage.tsx   |   143 +
 .../src/paths/instance/templates/use/index.tsx     |   101 +
 .../src/paths/instance/token/DetailPage.tsx        |   183 +
 .../src/paths/instance/token/index.tsx             |   106 +
 .../src/paths/instance/token/stories.tsx           |    28 +
 .../instance/transfers/create/Create.stories.tsx   |    45 +
 .../paths/instance/transfers/create/CreatePage.tsx |   146 +
 .../src/paths/instance/transfers/create/index.tsx  |    68 +
 .../paths/instance/transfers/list/List.stories.tsx |    93 +
 .../src/paths/instance/transfers/list/ListPage.tsx |   134 +
 .../src/paths/instance/transfers/list/Table.tsx    |   229 +
 .../src/paths/instance/transfers/list/index.tsx    |   118 +
 .../src/paths/instance/transfers/update/index.tsx  |    26 +
 .../src/paths/instance/update/Update.stories.tsx   |    59 +
 .../src/paths/instance/update/UpdatePage.tsx       |   176 +
 .../src/paths/instance/update/index.tsx            |   118 +
 .../instance/webhooks/create/Create.stories.tsx    |    28 +
 .../paths/instance/webhooks/create/CreatePage.tsx  |   183 +
 .../src/paths/instance/webhooks/create/index.tsx   |    61 +
 .../paths/instance/webhooks/list/List.stories.tsx  |    28 +
 .../src/paths/instance/webhooks/list/ListPage.tsx  |    64 +
 .../src/paths/instance/webhooks/list/Table.tsx     |   218 +
 .../src/paths/instance/webhooks/list/index.tsx     |   109 +
 .../instance/webhooks/update/Update.stories.tsx    |    32 +
 .../paths/instance/webhooks/update/UpdatePage.tsx  |   146 +
 .../src/paths/instance/webhooks/update/index.tsx   |    99 +
 .../src/paths/login/index.tsx                      |   202 +
 .../src/paths/notfound/index.tsx                   |    34 +
 .../src/paths/settings/index.tsx                   |   112 +
 .../auditor-backoffice-ui/src/schemas/index.ts     |   245 +
 .../src/scss/DurationPicker.scss                   |    70 +
 .../auditor-backoffice-ui/src/scss/_aside.scss     |   181 +
 packages/auditor-backoffice-ui/src/scss/_card.scss |    69 +
 .../src/scss/_custom-calendar.scss                 |   259 +
 .../auditor-backoffice-ui/src/scss/_footer.scss    |    35 +
 packages/auditor-backoffice-ui/src/scss/_form.scss |    71 +
 .../auditor-backoffice-ui/src/scss/_hero-bar.scss  |    55 +
 .../auditor-backoffice-ui/src/scss/_loading.scss   |    51 +
 .../src/scss/_main-section.scss                    |    24 +
 packages/auditor-backoffice-ui/src/scss/_misc.scss |    50 +
 .../auditor-backoffice-ui/src/scss/_mixins.scss    |    34 +
 .../auditor-backoffice-ui/src/scss/_modal.scss     |    35 +
 .../auditor-backoffice-ui/src/scss/_nav-bar.scss   |   144 +
 .../auditor-backoffice-ui/src/scss/_table.scss     |   179 +
 .../src/scss/_theme-default.scss                   |   136 +
 .../auditor-backoffice-ui/src/scss/_tiles.scss     |    24 +
 .../auditor-backoffice-ui/src/scss/_title-bar.scss |    50 +
 .../src/scss/fonts/XRXV3I6Li01BKofINeaE.ttf        |   Bin 0 -> 43752 bytes
 .../src/scss/fonts/nunito.css                      |    22 +
 .../fonts/materialdesignicons-webfont-4.9.95.eot   |   Bin 0 -> 844600 bytes
 .../fonts/materialdesignicons-webfont-4.9.95.ttf   |   Bin 0 -> 844380 bytes
 .../fonts/materialdesignicons-webfont-4.9.95.woff  |   Bin 0 -> 404384 bytes
 .../fonts/materialdesignicons-webfont-4.9.95.woff2 |   Bin 0 -> 283040 bytes
 .../scss/icons/materialdesignicons-4.9.95.min.css  | 15109 +++++++++++++++++++
 .../auditor-backoffice-ui/src/scss/libs/_all.scss  |    29 +
 packages/auditor-backoffice-ui/src/scss/main.scss  |   195 +
 .../auditor-backoffice-ui/src/scss/toggle.scss     |    51 +
 packages/auditor-backoffice-ui/src/stories.test.ts |    44 +
 packages/auditor-backoffice-ui/src/stories.tsx     |    48 +
 packages/auditor-backoffice-ui/src/sw.js           |    25 +
 packages/auditor-backoffice-ui/src/utils/amount.ts |    71 +
 .../auditor-backoffice-ui/src/utils/constants.ts   |   197 +
 packages/auditor-backoffice-ui/src/utils/crypto.ts |    61 +
 .../auditor-backoffice-ui/src/utils/regex.test.ts  |    88 +
 packages/auditor-backoffice-ui/src/utils/table.ts  |    57 +
 packages/auditor-backoffice-ui/src/utils/types.ts  |    31 +
 packages/auditor-backoffice-ui/test.mjs            |    31 +
 packages/auditor-backoffice-ui/tsconfig.json       |    58 +
 283 files changed, 79533 insertions(+), 1 deletion(-)

diff --git a/packages/aml-backoffice-ui/src/context/config.ts 
b/packages/aml-backoffice-ui/src/context/config.ts
index 3f62258c6..baf3445c4 100644
--- a/packages/aml-backoffice-ui/src/context/config.ts
+++ b/packages/aml-backoffice-ui/src/context/config.ts
@@ -60,7 +60,8 @@ export const ExchangeApiProvider = ({
 }): VNode => {
   const [checked, setChecked] = useState<ConfigResult>()
   const { i18n } = useTranslationContext();
-  const url = new URL(baseUrl)
+  //const url = new URL(baseUrl)
+  const url = new URL("http://localhost:8081";);
   const api = new TalerExchangeHttpClient(url.href, new BrowserHttpLib())
   useEffect(() => {
     api.getConfig()
diff --git a/packages/auditor-backoffice-ui/.gitignore 
b/packages/auditor-backoffice-ui/.gitignore
new file mode 100644
index 000000000..df149101c
--- /dev/null
+++ b/packages/auditor-backoffice-ui/.gitignore
@@ -0,0 +1,6 @@
+/build
+/size-plugin.json
+/storybook-static
+/docs
+/single
+/coverage
diff --git a/packages/auditor-backoffice-ui/DESIGN.md 
b/packages/auditor-backoffice-ui/DESIGN.md
new file mode 100644
index 000000000..d6252ccdc
--- /dev/null
+++ b/packages/auditor-backoffice-ui/DESIGN.md
@@ -0,0 +1,195 @@
+# Page internal routing
+
+* The SPA is loaded from the BACKOFFICE_URL
+
+* The view to be rendered is decided by the URL fragment
+
+* Query parameters that may affect routing
+
+  - instance: use from the default instance to mimic another instance 
management
+
+* The user must provide BACKEND_URL or BACKOFFICE_URL will use as default
+
+* Token for querying the backend will be saved in localStorage under
+  backend-token-${name}
+
+# HTTP queries to the backend
+
+HTTP queries will have 4 states:
+
+* loading: request did not end yet. data and error are undefined
+
+* ok: data has information, http response status == 200
+
+* clientError: http response status is between 400 and 499
+
+  - notfound: http status 404
+
+  - unauthorized: http status 401
+
+* serverError: http response status is grater than 500
+
+There are categories of queries:
+
+ * sync: getting information for the page rendering
+
+ * async: performing an CRUD operation  
+
+## Loading the page information (sync)
+
+In this scenario, a failed request will make the app flow to break.
+
+When receiving an not found error a generic not found page will be shown. If 
the
+BACKEND_URL points to a default instance it should send the user to create the
+instance.
+
+When receiving an unauthorized error, the user should be prompted with a login 
form.
+
+When receiving an another error (400 < http status < 600), the login form 
should
+be shown with an error message using the hint from the backend.
+
+On other unexpected error (like network error), the login form should be shown
+with an error message.
+
+## CRUD operation (async)
+
+In this scenario, a failed request does not break the flow but a message will 
be
+prompted.
+
+# Forms
+
+All the input components should be placed in the folder `src/components/from`.
+
+The core concepts are:
+
+ * <FormProvider<T> /> places instead of <form /> it should be mapped to an
+   object of type T
+
+ * <Input /> an others: defines UI, create <input /> DOM controls and access 
the
+   form with useField()
+
+To use it you will need a state somewhere with the object holding all the form
+information.
+
+```
+const [state, setState] = useState({ name: '', age: 11 })
+```
+
+Optionally an error object an be built with the error messages
+
+```
+const errors = {
+  field1: undefined,
+  field2: 'should be greater than 18',
+}
+```
+
+These 3 elements are used to setup the FormProvider
+
+```
+<FormProvider errors={errors} object={state} valueHandler={setState}>
+...inputs
+</FormProvider>
+```
+
+Inputs should handle UI rendering and use `useField(name)` to get:
+
+  * error: the field has been modified and the value is not correct
+  * required: the field need to be corrected
+  * value: the current value of the object
+  * initial: original value before change
+  * onChange: function to update the current field
+
+Also, every input must be ready to receive these properties
+
+  * name: property of the form object being manipulated
+  * label: how the name of the property will be shown in the UI
+  * placeholder: optional, inplace text when there is no value yet
+  * readonly: default to false, will prevent change the value
+  * help: optional, example text below the input text to help the user
+  * tooltip: optional, will add a (i) with a popup to describe the field
+
+
+# Custom Hooks
+
+All the general purpose hooks should be placed in folder `src/hooks` and tests
+under `tests/hooks`. Starts with the `use` word.
+
+# Contexts
+
+All the contexts should be placed in the folder `src/context` as a function.
+Should expose provider as a component `<XxxContextProvider />` and consumer as 
a
+hook function `useXxxContext()` (where XXX is the name)
+
+# Components
+
+Type of components:
+
+ * main entry point: src/index.tsx, mostly initialization
+
+ * routing: in the `src` folder, deciding who is going to take the work. That's
+   when the page is loading but also create navigation handlers
+
+ * pages: in the `paths` folder, setup page information (like querying the
+   backend for the list of things), handlers for CRUD events, delegated routing
+   to parent and UI to children.
+
+Some other guidelines:
+
+ * Hooks over classes are preferred
+
+ * Components that are ready to be reused on any place should be in
+   `src/components` folder
+
+ * Since one of the build targets is a single bundle with all the pages, we are
+   avoiding route based code splitting
+   https://github.com/preactjs/preact-cli#route-based-code-splitting
+
+
+# Testing
+
+Every components should have examples using storybook (xxx.stories.tsx). There
+is an automated test that check that every example can be rendered so we make
+sure that we do not add a regression.
+
+Every hook should have examples under `tests/hooks` with common usage trying to
+follow this structure:
+
+ * (Given) set some context of the initial condition
+
+ * (When) some action to be tested. May be the initialization of a hook or an
+   action associated with it
+
+ * (Then) a particular set of observable consequences should be expected
+
+# Accessibility 
+
+Pages and components should be built with accessibility in mind. 
+ 
+https://github.com/nickcolley/jest-axe
+https://orkhanhuseyn.medium.com/accessibility-testing-in-react-with-jest-axe-e08c2a3f3289
+http://accesibilidadweb.dlsi.ua.es/?menu=jaws
+https://webaim.org/projects/screenreadersurvey8/#intro
+https://www.gov.uk/service-manual/technology/testing-with-assistive-technologies#how-to-test
+https://es.reactjs.org/docs/accessibility.html
+
+# Internationalization
+
+Every non translated message should be written in English and wrapped into:
+
+ * i18n function from useTranslator() hook
+ * <Translate /> component
+
+Makefile has a i18n that will parse source files and update the po template.
+When *.po are updated, running the i18n target will create the strings.ts that
+the application will use in runtime.
+
+# Documentation Conventions
+
+* labels
+  * begin w/ a capital letter
+  * acronyms (e.g., "URL") are upper case
+* tooltips
+  * begin w/ a lower case letter
+  * do not end w/ punctuation (period)
+  * avoid leading article ("a", "an", "the")
diff --git a/packages/auditor-backoffice-ui/Makefile 
b/packages/auditor-backoffice-ui/Makefile
new file mode 100644
index 000000000..57b3e0cb5
--- /dev/null
+++ b/packages/auditor-backoffice-ui/Makefile
@@ -0,0 +1,35 @@
+# This Makefile has been placed in the public domain
+
+ifeq ($(TOPLEVEL), yes)
+  $(info top-level build)
+  -include ../../.config.mk
+  override DESTDIR := $(TOP_DESTDIR)
+else
+  $(info package-level build)
+  -include ../../.config.mk
+  -include .config.mk
+endif
+
+$(info prefix is $(prefix))
+
+.PHONY: all
+all:
+       @echo run \'make install\' to install
+
+spa_dir=$(DESTDIR)$(prefix)/share/taler/auditor-backoffice
+
+.PHONY: deps
+deps:
+       pnpm install --frozen-lockfile --filter @gnu-taler/auditor-backoffice...
+       pnpm run build
+
+.PHONY: install-nodeps
+install-nodeps:
+       (cd dist/prod && find . -type f -exec install -D "{}" "$(spa_dir)/{}" 
\;)
+
+
+.PHONY: install
+install:
+       $(MAKE) deps
+       $(MAKE) install-nodeps
+
diff --git a/packages/auditor-backoffice-ui/README.md 
b/packages/auditor-backoffice-ui/README.md
new file mode 100644
index 000000000..b10fa6a94
--- /dev/null
+++ b/packages/auditor-backoffice-ui/README.md
@@ -0,0 +1,64 @@
+## AUditor Admin Frontend
+
+Auditor Admin Frontend is a Single Page Application (SPA) that connects with a 
running Auditor Backend and lets you audit the exchange.
+
+## System requirements
+
+- Node: v16.15.0
+- pnpm: 7.14.2
+- make
+
+## Compiling from source
+
+Run `pnpm install --frozen-lockfile --filter @gnu-taler/auditor-backoffice...` 
to install all the nodejs dependencies.
+
+Then the command `pnpm build` create the distribution in the `dist` folder.
+
+By default the installation prefix will be 
`/usr/local/share/taler/auditor-backoffice/` but it can be overridden by 
`--prefix` in the configuration process:
+
+```shell
+./configure --prefix=/another/directory
+```
+
+To install run `make install`
+
+## Running develop
+
+To run a development server run:
+
+```shell
+./dev.mjs
+```
+
+This should start a watch process that will reload the server every time that 
a file is saved.
+
+The application need to connect to a auditor-backend properly configured to 
run.
+
+## Building for deploy
+
+To build and deploy the SPA in your local server run the install script:
+
+```shell
+make install
+```
+
+## Runtime dependencies
+
+*   preact: Fast 3kB alternative to React with the same modern API
+
+*   preact-router: URL component router for Preact
+
+*   SWR: React Hooks library for data fetching (stale-while-revalidate)
+
+*   Yup: schema builder for value parsing and validation (to be deprecated)
+
+*   Date-fns: library for manipulating javascript date
+
+*   qrcode-generator: simplest qr implementation based on JIS X 0510:1999
+
+*   @gnu-taler/taler-util: types and tooling
+
+*   history: manage the history stack, navigate, and persist state between 
sessions
+
+*   jed: gettext like library for internationalization
+
diff --git a/packages/auditor-backoffice-ui/build.mjs 
b/packages/auditor-backoffice-ui/build.mjs
new file mode 100755
index 000000000..b6d6e5127
--- /dev/null
+++ b/packages/auditor-backoffice-ui/build.mjs
@@ -0,0 +1,28 @@
+#!/usr/bin/env node
+/*
+ This file is part of GNU Taler
+ (C) 2021-2023 Taler Systems S.A.
+
+ GNU Taler is free software; you can redistribute it and/or modify it under the
+ terms of the GNU General Public License as published by the Free Software
+ Foundation; either version 3, or (at your option) any later version.
+
+ GNU Taler is distributed in the hope that it will be useful, but WITHOUT ANY
+ WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
+ A PARTICULAR PURPOSE.  See the GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License along with
+ GNU Taler; see the file COPYING.  If not, see <http://www.gnu.org/licenses/>
+ */
+
+import { build } from "@gnu-taler/web-util/build";
+
+await build({
+  type: "production",
+  source: {
+    js: ["src/index.tsx"],
+    assets: [{base:"src",files:["src/index.html"]}],
+  },
+  destination: "./dist/prod",
+  css: "sass",
+});
diff --git a/packages/auditor-backoffice-ui/contrib/po2ts 
b/packages/auditor-backoffice-ui/contrib/po2ts
new file mode 100755
index 000000000..d32e922ba
--- /dev/null
+++ b/packages/auditor-backoffice-ui/contrib/po2ts
@@ -0,0 +1,42 @@
+#!/usr/bin/env node
+/*
+ This file is part of GNU Taler
+ (C) 2024 Taler Systems S.A.
+
+ GNU Taler is free software; you can redistribute it and/or modify it under the
+ terms of the GNU General Public License as published by the Free Software
+ Foundation; either version 3, or (at your option) any later version.
+
+ GNU Taler is distributed in the hope that it will be useful, but WITHOUT ANY
+ WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
+ A PARTICULAR PURPOSE.  See the GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License along with
+ GNU Taler; see the file COPYING.  If not, see <http://www.gnu.org/licenses/>
+ */
+
+/**
+ * Convert a <lang>.po file into a JavaScript / TypeScript expression.
+ */
+
+const po2json = require("po2json");
+
+const filename = process.argv[2];
+
+if (!filename) {
+  console.error("error: missing filename");
+  process.exit(1);
+}
+
+const m = filename.match(/([a-zA-Z0-9-_]+).po/);
+
+if (!m) {
+  console.error("error: unexpected filename (expected <lang>.po)");
+  process.exit(1);
+}
+
+const lang = m[1];
+const pojson = po2json.parseFileSync(filename, { format: "jed1.x", fuzzy: true 
});
+const s =
+  "strings['" + lang + "'] = " + JSON.stringify(pojson, null, "  ") + ";\n";
+console.log(s);
diff --git a/packages/auditor-backoffice-ui/copyleft-header.js 
b/packages/auditor-backoffice-ui/copyleft-header.js
new file mode 100644
index 000000000..2589fdc92
--- /dev/null
+++ b/packages/auditor-backoffice-ui/copyleft-header.js
@@ -0,0 +1,15 @@
+/*
+ This file is part of GNU Taler
+ (C) 2021-2024 Taler Systems S.A.
+
+ GNU Taler is free software; you can redistribute it and/or modify it under the
+ terms of the GNU General Public License as published by the Free Software
+ Foundation; either version 3, or (at your option) any later version.
+
+ GNU Taler is distributed in the hope that it will be useful, but WITHOUT ANY
+ WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
+ A PARTICULAR PURPOSE.  See the GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License along with
+ GNU Taler; see the file COPYING.  If not, see <http://www.gnu.org/licenses/>
+ */
diff --git a/packages/auditor-backoffice-ui/dev.mjs 
b/packages/auditor-backoffice-ui/dev.mjs
new file mode 100755
index 000000000..14d5737de
--- /dev/null
+++ b/packages/auditor-backoffice-ui/dev.mjs
@@ -0,0 +1,40 @@
+#!/usr/bin/env node
+/*
+ This file is part of GNU Taler
+ (C) 2021-2024 Taler Systems S.A.
+
+ GNU Taler is free software; you can redistribute it and/or modify it under the
+ terms of the GNU General Public License as published by the Free Software
+ Foundation; either version 3, or (at your option) any later version.
+
+ GNU Taler is distributed in the hope that it will be useful, but WITHOUT ANY
+ WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
+ A PARTICULAR PURPOSE.  See the GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License along with
+ GNU Taler; see the file COPYING.  If not, see <http://www.gnu.org/licenses/>
+ */
+
+import { serve } from "@gnu-taler/web-util/node";
+import { initializeDev } from "@gnu-taler/web-util/build";
+
+const devEntryPoints = ["src/stories.tsx", "src/index.tsx"];
+
+const build = initializeDev({
+  type: "development",
+  source: {
+    js: devEntryPoints,
+    assets: [{base:"src",files:["src/index.html"]}],
+  },
+  css: "sass",
+  destination: "./dist/dev",
+});
+
+await build();
+
+serve({
+  folder: "./dist/dev",
+  port: 8080,
+  source: "./src",
+  onSourceUpdate: build,
+});
diff --git a/packages/auditor-backoffice-ui/package.json 
b/packages/auditor-backoffice-ui/package.json
new file mode 100644
index 000000000..1fe7332c0
--- /dev/null
+++ b/packages/auditor-backoffice-ui/package.json
@@ -0,0 +1,83 @@
+{
+  "private": true,
+  "name": "@gnu-taler/auditor-backoffice-ui",
+  "version": "0.9.3-dev.27",
+  "license": "AGPL-3.0-or-later",
+  "type": "module",
+  "scripts": {
+    "build": "./build.mjs",
+    "check": "tsc",
+    "compile": "tsc && ./build.mjs",
+    "dev": "preact watch --port ${PORT:=8080} --no-sw --no-esm",
+    "test": "./test.mjs && mocha --require source-map-support/register 
'dist/**/*.test.js' 'dist/**/test.js'",
+    "lint": "eslint 'src/**/*.{js,jsx,ts,tsx}'",
+    "i18n:extract": "pogen extract",
+    "i18n:merge": "pogen merge",
+    "i18n:emit": "pogen emit",
+    "i18n": "pnpm i18n:extract && pnpm i18n:merge && pnpm i18n:emit",
+    "typedoc": "typedoc --out dist/typedoc ./src/",
+    "pretty": "prettier --write src"
+  },
+  "eslintConfig": {
+    "plugins": [
+      "header"
+    ],
+    "rules": {
+      "header/header": [
+        2,
+        "copyleft-header.js"
+      ]
+    },
+    "extends": [
+      "prettier"
+    ]
+  },
+  "dependencies": {
+    "@gnu-taler/taler-util": "workspace:*",
+    "@gnu-taler/web-util": "workspace:*",
+    "date-fns": "2.29.3",
+    "history": "4.10.1",
+    "jed": "1.1.1",
+    "preact": "10.11.3",
+    "preact-router": "3.2.1",
+    "qrcode-generator": "1.4.4",
+    "swr": "2.2.2",
+    "yup": "^0.32.9"
+  },
+  "devDependencies": {
+    "@creativebulma/bulma-tooltip": "^1.2.0",
+    "@gnu-taler/pogen": "^0.0.5",
+    "@types/chai": "^4.3.0",
+    "@types/history": "^4.7.8",
+    "@types/mocha": "^8.2.3",
+    "@types/node": "^18.11.17",
+    "@typescript-eslint/eslint-plugin": "^4.22.0",
+    "@typescript-eslint/parser": "^4.22.0",
+    "base64-inline-loader": "^1.1.1",
+    "bulma": "^0.9.2",
+    "bulma-checkbox": "^1.1.1",
+    "bulma-radio": "^1.1.1",
+    "bulma-responsive-tables": "^1.2.3",
+    "bulma-switch-control": "^1.1.1",
+    "bulma-timeline": "^3.0.4",
+    "bulma-upload-control": "^1.2.0",
+    "chai": "^4.3.6",
+    "dotenv": "^8.2.0",
+    "eslint": "^7.25.0",
+    "eslint-config-preact": "^1.1.4",
+    "eslint-plugin-header": "^3.1.1",
+    "html-webpack-inline-chunk-plugin": "^1.1.1",
+    "html-webpack-inline-source-plugin": "0.0.10",
+    "html-webpack-skip-assets-plugin": "^1.0.1",
+    "inline-chunk-html-plugin": "^1.1.1",
+    "mocha": "^9.2.0",
+    "preact-render-to-string": "^5.2.6",
+    "sass": "1.56.1",
+    "source-map-support": "^0.5.21",
+    "typedoc": "^0.25.4",
+    "typescript": "5.3.3"
+  },
+  "pogen": {
+    "domain": "taler-auditor-backoffice"
+  }
+}
diff --git a/packages/auditor-backoffice-ui/preact.config.js 
b/packages/auditor-backoffice-ui/preact.config.js
new file mode 100644
index 000000000..9b65d3ec7
--- /dev/null
+++ b/packages/auditor-backoffice-ui/preact.config.js
@@ -0,0 +1,70 @@
+/*
+ This file is part of GNU Taler
+ (C) 2021-2024 Taler Systems S.A.
+
+ GNU Taler is free software; you can redistribute it and/or modify it under the
+ terms of the GNU General Public License as published by the Free Software
+ Foundation; either version 3, or (at your option) any later version.
+
+ GNU Taler is distributed in the hope that it will be useful, but WITHOUT ANY
+ WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
+ A PARTICULAR PURPOSE.  See the GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License along with
+ GNU Taler; see the file COPYING.  If not, see <http://www.gnu.org/licenses/>
+ */
+
+/**
+*
+* @author Sebastian Javier Marchano (sebasjm)
+*/
+
+import { DefinePlugin } from 'webpack';
+
+import pack from './package.json';
+import * as cp from 'child_process';
+
+const commitHash = cp.execSync('git rev-parse --short HEAD').toString();
+
+export default {
+  webpack(config, env, helpers) {
+    // ensure that process.env will not be undefined on runtime
+    config.node.process = 'mock'
+
+    // add __VERSION__ to be use in the html
+    config.plugins.push(
+      new DefinePlugin({
+        'process.env.__VERSION__': JSON.stringify(env.isProd ? pack.version : 
`dev-${commitHash}`) ,
+      }),
+    );
+
+    // suddenly getting out of memory error from build process, error below [1]
+    // FIXME: remove preact-cli, use rollup
+    let { index } = helpers.getPluginsByName(config, 
'WebpackFixStyleOnlyEntriesPlugin')[0]
+    config.plugins.splice(index, 1)   
+  }
+}
+
+
+
+/* [1] from this error decided to remove plugin 'webpack-fix-style-only-entries
+   leaving this error for future reference
+
+
+<--- Last few GCs --->
+
+[32479:0x2e01870]    19969 ms: Mark-sweep 1869.4 (1950.2) -> 1443.1 (1504.1) 
MB, 497.5 / 0.0 ms  (average mu = 0.631, current mu = 0.455) allocation failure 
scavenge might not succeed
+[32479:0x2e01870]    21907 ms: Mark-sweep 2016.9 (2077.9) -> 1628.6 (1681.4) 
MB, 1596.0 / 0.0 ms  (average mu = 0.354, current mu = 0.176) allocation 
failure scavenge might not succeed
+
+<--- JS stacktrace --->
+
+==== JS stack trace =========================================
+
+    0: ExitFrame [pc: 0x13cf099]
+Security context: 0x2f4ca66c08d1 <JSObject>
+    1: /* anonymous * / [0x35d05555b4b9] 
[...path/merchant-backoffice/node_modules/.pnpm/webpack-fix-style-only-entries@0.5.2/node_modules/webpack-fix-style-only-entries/index.js:~80]
 [pc=0x2145e699d1a4](this=0x1149465410e9 <GlobalObject Object map = 
0xff481b5b5f9>,0x047e52e36a49 <Dependency map = 0x1ed1fe41cd19>)
+    2: arguments adaptor frame: 3...
+
+FATAL ERROR: invalid array length Allocation failed - JavaScript heap out of 
memory
+ 
+*/
\ No newline at end of file
diff --git a/packages/auditor-backoffice-ui/preact.single-config.js 
b/packages/auditor-backoffice-ui/preact.single-config.js
new file mode 100644
index 000000000..849269d6e
--- /dev/null
+++ b/packages/auditor-backoffice-ui/preact.single-config.js
@@ -0,0 +1,62 @@
+/*
+ This file is part of GNU Taler
+ (C) 2021-2024 Taler Systems S.A.
+
+ GNU Taler is free software; you can redistribute it and/or modify it under the
+ terms of the GNU General Public License as published by the Free Software
+ Foundation; either version 3, or (at your option) any later version.
+
+ GNU Taler is distributed in the hope that it will be useful, but WITHOUT ANY
+ WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
+ A PARTICULAR PURPOSE.  See the GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License along with
+ GNU Taler; see the file COPYING.  If not, see <http://www.gnu.org/licenses/>
+ */
+
+/**
+*
+* @author Sebastian Javier Marchano (sebasjm)
+*/
+
+import defaultConfig from './preact.config'
+
+export default {
+  webpack(config, env, helpers, options) {
+    defaultConfig.webpack(config, env, helpers, options)
+
+    //1. check no file is under /routers or /component/{routers,async} to 
prevent async components
+    // https://github.com/preactjs/preact-cli#route-based-code-splitting
+
+    //2. remove devtools to prevent sourcemaps
+    config.devtool = false
+
+    //3. change assetLoader to load assets inline
+    const loaders = helpers.getLoaders(config)
+    const assetsLoader = loaders.find(lo => 
lo.rule.test.test('something.woff'))
+    if (assetsLoader) {
+      assetsLoader.rule.use = 'base64-inline-loader'
+      assetsLoader.rule.loader = undefined
+    }
+
+    //4. remove critters
+    //critters remove the css bundle from htmlWebpackPlugin.files.css
+    //for now, pushing all the content into the html is enough
+    const crittersWrapper = helpers.getPluginsByName(config, 'Critters')
+    if (crittersWrapper && crittersWrapper.length > 0) {
+      const [{ index }] = crittersWrapper
+      config.plugins.splice(index, 1)
+    }
+
+    //5. remove favicon from src/assets
+
+    //6. remove performance hints since we now that this is going to be big
+    if (config.performance) {
+      config.performance.hints = false
+    }
+
+    //7. template.html should have a favicon and add js/css content
+
+    //last, after building remove the mysterious link to stylesheet with 
remove-link-stylesheet.sh
+  }
+}
diff --git a/packages/auditor-backoffice-ui/remove-link-stylesheet.sh 
b/packages/auditor-backoffice-ui/remove-link-stylesheet.sh
new file mode 100644
index 000000000..fdf8f241c
--- /dev/null
+++ b/packages/auditor-backoffice-ui/remove-link-stylesheet.sh
@@ -0,0 +1,8 @@
+# This script has been placed in the public domain.
+
+FILE=$(ls single/bundle.*.css)
+BUNDLE=${FILE#single}
+grep -q '<link href="'$BUNDLE'" rel="stylesheet">' single/index.html || { echo 
bundle $BUNDLE not found in index.html; exit 1; }
+echo -n Removing link from index.html ...
+sed 's_<link href="'$BUNDLE'" rel="stylesheet">__' -i single/index.html
+echo done
diff --git a/packages/auditor-backoffice-ui/src/AdminRoutes.tsx 
b/packages/auditor-backoffice-ui/src/AdminRoutes.tsx
new file mode 100644
index 000000000..91dec09b0
--- /dev/null
+++ b/packages/auditor-backoffice-ui/src/AdminRoutes.tsx
@@ -0,0 +1,53 @@
+/*
+ This file is part of GNU Taler
+ (C) 2021-2023 Taler Systems S.A.
+
+ GNU Taler is free software; you can redistribute it and/or modify it under the
+ terms of the GNU General Public License as published by the Free Software
+ Foundation; either version 3, or (at your option) any later version.
+
+ GNU Taler is distributed in the hope that it will be useful, but WITHOUT ANY
+ WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
+ A PARTICULAR PURPOSE.  See the GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License along with
+ GNU Taler; see the file COPYING.  If not, see <http://www.gnu.org/licenses/>
+ */
+import { h, VNode } from "preact";
+import { Router, route, Route } from "preact-router";
+import InstanceCreatePage from "./paths/admin/create/index.js";
+import InstanceListPage from "./paths/admin/list/index.js";
+
+export enum AdminPaths {
+  list_instances = "/instances",
+  new_instance = "/instance/new",
+}
+
+export function AdminRoutes(): VNode {
+  return (
+    <Router>
+      <Route
+        path={AdminPaths.list_instances}
+        component={InstanceListPage}
+        onCreate={() => {
+          route(AdminPaths.new_instance);
+        }}
+        onUpdate={(id: string): void => {
+          route(`/instance/${id}/update`);
+        }}
+      />
+
+      <Route
+        path={AdminPaths.new_instance}
+        component={InstanceCreatePage}
+        onBack={() => route(AdminPaths.list_instances)}
+        onConfirm={() => {
+          // route(AdminPaths.list_instances);
+        }}
+
+        // onError={(error: any) => {
+        // }}
+      />
+    </Router>
+  );
+}
diff --git a/packages/auditor-backoffice-ui/src/Application.tsx 
b/packages/auditor-backoffice-ui/src/Application.tsx
new file mode 100644
index 000000000..e832d3107
--- /dev/null
+++ b/packages/auditor-backoffice-ui/src/Application.tsx
@@ -0,0 +1,165 @@
+/*
+ This file is part of GNU Taler
+ (C) 2021-2023 Taler Systems S.A.
+
+ GNU Taler is free software; you can redistribute it and/or modify it under the
+ terms of the GNU General Public License as published by the Free Software
+ Foundation; either version 3, or (at your option) any later version.
+
+ GNU Taler is distributed in the hope that it will be useful, but WITHOUT ANY
+ WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
+ A PARTICULAR PURPOSE.  See the GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License along with
+ GNU Taler; see the file COPYING.  If not, see <http://www.gnu.org/licenses/>
+ */
+
+/**
+ *
+ * @author Sebastian Javier Marchano (sebasjm)
+ */
+
+import { HttpStatusCode, LibtoolVersion } from "@gnu-taler/taler-util";
+import {
+  ErrorType,
+  TranslationProvider,
+  useTranslationContext,
+} from "@gnu-taler/web-util/browser";
+import { Fragment, VNode, h } from "preact";
+import { useMemo } from "preact/hooks";
+import { ApplicationReadyRoutes } from "./ApplicationReadyRoutes.js";
+import { Loading } from "./components/exception/loading.js";
+import {
+  NotConnectedAppMenu,
+  NotificationCard
+} from "./components/menu/index.js";
+import {
+  BackendContextProvider
+} from "./context/backend.js";
+import { ConfigContextProvider } from "./context/config.js";
+import { useBackendConfig } from "./hooks/backend.js";
+import { strings } from "./i18n/strings.js";
+
+export function Application(): VNode {
+  return (
+    <BackendContextProvider>
+      <TranslationProvider source={strings}>
+        <ApplicationStatusRoutes />
+      </TranslationProvider>
+    </BackendContextProvider>
+  );
+}
+
+/**
+ * Check connection testing against /config
+ * 
+ * @returns 
+ */
+function ApplicationStatusRoutes(): VNode {
+  const result = useBackendConfig();
+  const { i18n } = useTranslationContext();
+
+  const { currency, version } = result.ok && result.data
+    ? result.data
+    : { currency: "unknown", version: "unknown" };
+  const ctx = useMemo(() => ({ currency, version }), [currency, version]);
+
+  if (!result.ok) {
+    if (result.loading) return <Loading />;
+    if (
+      result.type === ErrorType.CLIENT &&
+      result.status === HttpStatusCode.Unauthorized
+    ) {
+      return (
+        <Fragment>
+          <NotConnectedAppMenu title="Login" />
+          <NotificationCard
+            notification={{
+              message: i18n.str`Checking the /config endpoint got 
authorization error`,
+              type: "ERROR",
+              description: `The /config endpoint of the backend server should 
be accesible`,
+            }}
+          />
+        </Fragment>
+      );
+    }
+    if (
+      result.type === ErrorType.CLIENT &&
+      result.status === HttpStatusCode.NotFound
+    ) {
+      return (
+        <Fragment>
+          <NotConnectedAppMenu title="Error" />
+          <NotificationCard
+            notification={{
+              message: i18n.str`Could not find /config enpoint on this URL`,
+              type: "ERROR",
+              description: `Check the URL or contact the system 
administrator.`,
+            }}
+          />
+        </Fragment>
+      );
+    }
+    if (result.type === ErrorType.SERVER) {
+      <Fragment>
+        <NotConnectedAppMenu title="Error" />
+        <NotificationCard
+          notification={{
+            message: i18n.str`Server response with an error code`,
+            type: "ERROR",
+            description: i18n.str`Got message "${result.message}" from 
${result.info?.url}`,
+          }}
+        />
+      </Fragment>;
+    }
+    if (result.type === ErrorType.UNREADABLE) {
+      <Fragment>
+        <NotConnectedAppMenu title="Error" />
+        <NotificationCard
+          notification={{
+            message: i18n.str`Response from server is unreadable, http status: 
${result.status}`,
+            type: "ERROR",
+            description: i18n.str`Got message "${result.message}" from 
${result.info?.url}`,
+          }}
+        />
+      </Fragment>;
+    }
+    return (
+      <Fragment>
+        <NotConnectedAppMenu title="Error" />
+        <NotificationCard
+          notification={{
+            message: i18n.str`Unexpected Error`,
+            type: "ERROR",
+            description: i18n.str`Got message "${result.message}" from 
${result.info?.url}`,
+          }}
+        />
+      </Fragment>
+    );
+  }
+
+  const SUPPORTED_VERSION = "5:0:1"
+  if (result.data && !LibtoolVersion.compare(
+    SUPPORTED_VERSION,
+    result.data.version,
+  )?.compatible) {
+    return <Fragment>
+      <NotConnectedAppMenu title="Error" />
+      <NotificationCard
+        notification={{
+          message: i18n.str`Incompatible version`,
+          type: "ERROR",
+          description: i18n.str`Merchant backend server version 
${result.data.version} is not compatible with the supported version 
${SUPPORTED_VERSION}`,
+        }}
+      />
+    </Fragment>
+  }
+
+  return (
+    <div class="has-navbar-fixed-top">
+      <ConfigContextProvider value={ctx}>
+        <ApplicationReadyRoutes />
+      </ConfigContextProvider>
+    </div>
+  );
+}
diff --git a/packages/auditor-backoffice-ui/src/ApplicationReadyRoutes.tsx 
b/packages/auditor-backoffice-ui/src/ApplicationReadyRoutes.tsx
new file mode 100644
index 000000000..414eee39d
--- /dev/null
+++ b/packages/auditor-backoffice-ui/src/ApplicationReadyRoutes.tsx
@@ -0,0 +1,175 @@
+/*
+ This file is part of GNU Taler
+ (C) 2021-2024 Taler Systems S.A.
+
+ GNU Taler is free software; you can redistribute it and/or modify it under the
+ terms of the GNU General Public License as published by the Free Software
+ Foundation; either version 3, or (at your option) any later version.
+
+ GNU Taler is distributed in the hope that it will be useful, but WITHOUT ANY
+ WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
+ A PARTICULAR PURPOSE.  See the GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License along with
+ GNU Taler; see the file COPYING.  If not, see <http://www.gnu.org/licenses/>
+ */
+
+/**
+ *
+ * @author Sebastian Javier Marchano (sebasjm)
+ */
+import { HttpStatusCode } from "@gnu-taler/taler-util";
+import { ErrorType, useTranslationContext } from "@gnu-taler/web-util/browser";
+import { createHashHistory } from "history";
+import { Fragment, VNode, h } from "preact";
+import { Route, Router, route } from "preact-router";
+import { useState } from "preact/hooks";
+import { InstanceRoutes } from "./InstanceRoutes.js";
+import {
+  NotConnectedAppMenu,
+  NotYetReadyAppMenu,
+  NotificationCard,
+} from "./components/menu/index.js";
+import { useBackendContext } from "./context/backend.js";
+import { LoginToken } from "./declaration.js";
+import { useBackendInstancesTestForAdmin } from "./hooks/backend.js";
+import { LoginPage } from "./paths/login/index.js";
+import { Settings } from "./paths/settings/index.js";
+import { INSTANCE_ID_LOOKUP } from "./utils/constants.js";
+
+/**
+ * Check if admin against /management/instances
+ * @returns 
+ */
+export function ApplicationReadyRoutes(): VNode {
+  const { i18n } = useTranslationContext();
+  const [unauthorized, setUnauthorized] = useState(false)
+  const {
+    url: backendURL,
+    updateToken,
+    alreadyTriedLogin,
+  } = useBackendContext();
+
+  function updateLoginStatus(token: LoginToken | undefined) {
+    updateToken(token)
+    setUnauthorized(false)
+  }
+
+  const result = useBackendInstancesTestForAdmin();
+
+  const clearTokenAndGoToRoot = () => {
+    route("/");
+  };
+  const [showSettings, setShowSettings] = useState(false)
+  const unauthorizedAdmin = !result.loading
+    && !result.ok
+    && result.type === ErrorType.CLIENT
+    && result.status === HttpStatusCode.Unauthorized;
+
+  if (!alreadyTriedLogin && !result.ok) {
+    return (
+      <Fragment>
+        <NotConnectedAppMenu title="Welcome!" />
+        <LoginPage onConfirm={updateToken} />
+      </Fragment>
+    );
+  }
+
+  if (showSettings) {
+    return <Fragment>
+      <NotYetReadyAppMenu onShowSettings={() => setShowSettings(true)} 
title="UI Settings" onLogout={clearTokenAndGoToRoot} isPasswordOk={false} />
+      <Settings onClose={() => setShowSettings(false)} />
+    </Fragment>
+  }
+
+  if (result.loading) {
+    return <NotYetReadyAppMenu onShowSettings={() => setShowSettings(true)} 
title="Loading..." isPasswordOk={false} />;
+  }
+
+  let admin = result.ok || unauthorizedAdmin;
+  let instanceNameByBackendURL: string | undefined;
+
+  if (!admin) {
+    // * the testing against admin endpoint failed and it's not 
+    // an authorization problem
+    // * merchant backend will return this SPA under the main
+    // endpoint or /instance/<id> endpoint
+    // => trying to infer the instance id
+    const path = new URL(backendURL).pathname;
+    const match = INSTANCE_ID_LOOKUP.exec(path);
+    if (!match || !match[1]) {
+      // this should be rare because
+      // query to /config is ok but the URL
+      // does not match our pattern
+      return (
+        <Fragment>
+          <NotYetReadyAppMenu onShowSettings={() => setShowSettings(true)} 
title="Error" onLogout={clearTokenAndGoToRoot} isPasswordOk={false} />
+          <NotificationCard
+            notification={{
+              message: i18n.str`Couldn't access the server.`,
+              description: i18n.str`Could not infer instance id from url 
${backendURL}`,
+              type: "ERROR",
+            }}
+          />
+          {/* <ConnectionPage onConfirm={changeBackend} /> */}
+        </Fragment>
+      );
+    }
+
+    instanceNameByBackendURL = match[1];
+  }
+
+  if (unauthorized || unauthorizedAdmin) {
+    return <Fragment>
+      <NotYetReadyAppMenu onShowSettings={() => setShowSettings(true)} 
title="Login" onLogout={clearTokenAndGoToRoot} isPasswordOk={false} />
+      <NotificationCard
+        notification={{
+          message: i18n.str`Access denied`,
+          description: i18n.str`Check your token is valid`,
+          type: "ERROR",
+        }}
+      />
+      <LoginPage onConfirm={updateLoginStatus} />
+    </Fragment>
+  }
+
+  const history = createHashHistory();
+  return (
+    <Router history={history}>
+      <Route
+        default
+        component={DefaultMainRoute}
+        admin={admin}
+        onUnauthorized={() => setUnauthorized(true)}
+        onLoginPass={() => {
+          setUnauthorized(false)
+        }}
+        instanceNameByBackendURL={instanceNameByBackendURL}
+      />
+    </Router>
+  );
+}
+
+function DefaultMainRoute({
+  instance,
+  admin,
+  onUnauthorized,
+  onLoginPass,
+  instanceNameByBackendURL,
+  url, //from preact-router
+}: any): VNode {
+  const [instanceName, setInstanceName] = useState(
+    instanceNameByBackendURL || instance || "default",
+  );
+
+  return (
+    <InstanceRoutes
+      admin={admin}
+      path={url}
+      onUnauthorized={onUnauthorized}
+      onLoginPass={onLoginPass}
+      id={instanceName}
+      setInstanceName={setInstanceName}
+    />
+  );
+}
diff --git a/packages/auditor-backoffice-ui/src/InstanceRoutes.tsx 
b/packages/auditor-backoffice-ui/src/InstanceRoutes.tsx
new file mode 100644
index 000000000..14ccf773a
--- /dev/null
+++ b/packages/auditor-backoffice-ui/src/InstanceRoutes.tsx
@@ -0,0 +1,800 @@
+/*
+ This file is part of GNU Taler
+ (C) 2021-2023 Taler Systems S.A.
+
+ GNU Taler is free software; you can redistribute it and/or modify it under the
+ terms of the GNU General Public License as published by the Free Software
+ Foundation; either version 3, or (at your option) any later version.
+
+ GNU Taler is distributed in the hope that it will be useful, but WITHOUT ANY
+ WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
+ A PARTICULAR PURPOSE.  See the GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License along with
+ GNU Taler; see the file COPYING.  If not, see <http://www.gnu.org/licenses/>
+ */
+
+/**
+ *
+ * @author Sebastian Javier Marchano (sebasjm)
+ * @author Nic Eigel
+ */
+
+import {
+  useTranslationContext,
+  HttpError,
+  ErrorType,
+} from "@gnu-taler/web-util/browser";
+import { format } from "date-fns";
+import { Fragment, FunctionComponent, h, VNode } from "preact";
+import { Route, route, Router } from "preact-router";
+import { useCallback, useEffect, useMemo, useState } from "preact/hooks";
+import { Loading } from "./components/exception/loading.js";
+import { Menu, NotificationCard } from "./components/menu/index.js";
+import { useBackendContext } from "./context/backend.js";
+import { InstanceContextProvider } from "./context/instance.js";
+import {
+  useBackendDefaultToken,
+  useBackendInstanceToken,
+  useSimpleLocalStorage,
+} from "./hooks/index.js";
+import { useInstanceKYCDetails } from "./hooks/instance.js";
+import InstanceCreatePage from "./paths/admin/create/index.js";
+import InstanceListPage from "./paths/admin/list/index.js";
+import TokenPage from "./paths/instance/token/index.js";
+import ListKYCPage from "./paths/instance/kyc/list/index.js";
+import OrderCreatePage from "./paths/instance/orders/create/index.js";
+import OrderDetailsPage from "./paths/instance/orders/details/index.js";
+import OrderListPage from "./paths/instance/orders/list/index.js";
+import DepositConfirmationCreatePage from 
"./paths/instance/deposit_confirmations/create/index.js";
+import DepositConfirmationListPage from 
"./paths/instance/deposit_confirmations/list/index.js";
+import DepositConfirmationUpdatePage from 
"./paths/instance/deposit_confirmations/update/index.js";
+import ProductCreatePage from "./paths/instance/products/create/index.js";
+import ProductListPage from "./paths/instance/products/list/index.js";
+import ProductUpdatePage from "./paths/instance/products/update/index.js";
+import BankAccountCreatePage from "./paths/instance/accounts/create/index.js";
+import BankAccountListPage from "./paths/instance/accounts/list/index.js";
+import BankAccountUpdatePage from "./paths/instance/accounts/update/index.js";
+import ReservesCreatePage from "./paths/instance/reserves/create/index.js";
+import ReservesDetailsPage from "./paths/instance/reserves/details/index.js";
+import ReservesListPage from "./paths/instance/reserves/list/index.js";
+import TemplateCreatePage from "./paths/instance/templates/create/index.js";
+import TemplateUsePage from "./paths/instance/templates/use/index.js";
+import TemplateQrPage from "./paths/instance/templates/qr/index.js";
+import TemplateListPage from "./paths/instance/templates/list/index.js";
+import TemplateUpdatePage from "./paths/instance/templates/update/index.js";
+import WebhookCreatePage from "./paths/instance/webhooks/create/index.js";
+import WebhookListPage from "./paths/instance/webhooks/list/index.js";
+import WebhookUpdatePage from "./paths/instance/webhooks/update/index.js";
+import ValidatorCreatePage from "./paths/instance/otp_devices/create/index.js";
+import ValidatorListPage from "./paths/instance/otp_devices/list/index.js";
+import ValidatorUpdatePage from "./paths/instance/otp_devices/update/index.js";
+import TransferCreatePage from "./paths/instance/transfers/create/index.js";
+import TransferListPage from "./paths/instance/transfers/list/index.js";
+import InstanceUpdatePage, {
+  AdminUpdate as InstanceAdminUpdatePage,
+  Props as InstanceUpdatePageProps,
+} from "./paths/instance/update/index.js";
+import { LoginPage } from "./paths/login/index.js";
+import NotFoundPage from "./paths/notfound/index.js";
+import { Notification } from "./utils/types.js";
+import { LoginToken, MerchantBackend } from "./declaration.js";
+import { Settings } from "./paths/settings/index.js";
+import { dateFormatForSettings, useSettings } from "./hooks/useSettings.js";
+
+export enum InstancePaths {
+  error = "/error",
+  settings = "/settings",
+  token = "/token",
+
+  inventory_list = "/inventory",
+  inventory_update = "/inventory/:pid/update",
+  inventory_new = "/inventory/new",
+
+  deposit_confirmation_list = "/deposit-confirmation",
+  deposit_confirmation_update = "/deposit-confirmation/:pid/update",
+  deposit_confirmation_new = "/deposit-confirmation/new",
+
+  interface = "/interface",
+}
+
+// eslint-disable-next-line @typescript-eslint/no-empty-function
+const noop = () => { };
+
+export enum AdminPaths {
+  list_instances = "/instances",
+  new_instance = "/instance/new",
+  update_instance = "/instance/:id/update",
+}
+
+export interface Props {
+  id: string;
+  admin?: boolean;
+  path: string;
+  onUnauthorized: () => void;
+  onLoginPass: () => void;
+  setInstanceName: (s: string) => void;
+}
+
+export function InstanceRoutes({
+  id,
+  admin,
+  path,
+  // onUnauthorized,
+  onLoginPass,
+  setInstanceName,
+}: Props): VNode {
+  const [defaultToken, updateDefaultToken] = useBackendDefaultToken();
+  const [token, updateToken] = useBackendInstanceToken(id);
+  const { i18n } = useTranslationContext();
+
+  type GlobalNotifState = (Notification & { to: string }) | undefined;
+  const [globalNotification, setGlobalNotification] =
+    useState<GlobalNotifState>(undefined);
+
+  const changeToken = (token?: LoginToken) => {
+    if (admin) {
+      updateToken(token);
+    } else {
+      updateDefaultToken(token);
+    }
+    onLoginPass()
+  };
+  // const updateLoginStatus = (url: string, token?: string) => {
+  //   changeToken(token);
+  // };
+
+  const value = useMemo(
+    () => ({ id, token, admin, changeToken }),
+    [id, token, admin],
+  );
+
+  function ServerErrorRedirectTo(to: InstancePaths | AdminPaths) {
+    return function ServerErrorRedirectToImpl(
+      error: HttpError<MerchantBackend.ErrorDetail>,
+    ) {
+      if (error.type === ErrorType.TIMEOUT) {
+        setGlobalNotification({
+          message: i18n.str`The request to the backend take too long and was 
cancelled`,
+          description: i18n.str`Diagnostic from ${error.info.url} is 
"${error.message}"`,
+          type: "ERROR",
+          to,
+        });
+      } else {
+        setGlobalNotification({
+          message: i18n.str`The backend reported a problem: HTTP status 
#${error.status}`,
+          description: i18n.str`Diagnostic from ${error.info.url} is 
'${error.message}'`,
+          details:
+            error.type === ErrorType.CLIENT || error.type === ErrorType.SERVER
+              ? error.payload.detail
+              : undefined,
+          type: "ERROR",
+          to,
+        });
+      }
+      return <Redirect to={to} />;
+    };
+  }
+
+  // const LoginPageAccessDeniend = onUnauthorized
+  const LoginPageAccessDenied = () => {
+    return <Fragment>
+      <NotificationCard
+        notification={{
+          message: i18n.str`Access denied`,
+          description: i18n.str`Session expired or password changed.`,
+          type: "ERROR",
+        }}
+      />
+      <LoginPage onConfirm={changeToken} />
+    </Fragment>
+
+  }
+
+  function IfAdminCreateDefaultOr<T>(Next: FunctionComponent<any>) {
+    return function IfAdminCreateDefaultOrImpl(props?: T) {
+      if (admin && id === "default") {
+        return (
+          <Fragment>
+            <NotificationCard
+              notification={{
+                message: i18n.str`No 'default' instance configured yet.`,
+                description: i18n.str`Create a 'default' instance to begin 
using the merchant backoffice.`,
+                type: "INFO",
+              }}
+            />
+            <InstanceCreatePage
+              forceId="default"
+              onConfirm={() => {
+                route(InstancePaths.order_list);
+              }}
+            />
+          </Fragment>
+        );
+      }
+      if (props) {
+        return <Next {...props} />;
+      }
+      return <Next />;
+    };
+  }
+
+  const clearTokenAndGoToRoot = () => {
+    route("/");
+    // clear all tokens
+    updateToken(undefined)
+    updateDefaultToken(undefined)
+  };
+
+  return (
+    <InstanceContextProvider value={value}>
+      <Menu
+        instance={id}
+        admin={admin}
+        onShowSettings={() => {
+          route(InstancePaths.interface)
+        }}
+        path={path}
+        onLogout={clearTokenAndGoToRoot}
+        setInstanceName={setInstanceName}
+        isPasswordOk={defaultToken !== undefined}
+      />
+      <KycBanner />
+      <NotificationCard notification={globalNotification} />
+
+      <Router
+        onChange={(e) => {
+          const movingOutFromNotification =
+            globalNotification && e.url !== globalNotification.to;
+          if (movingOutFromNotification) {
+            setGlobalNotification(undefined);
+          }
+        }}
+      >
+        <Route path="/" component={Redirect} to={InstancePaths.order_list} />
+        {/**
+         * Admin pages
+         */}
+        {admin && (
+          <Route
+            path={AdminPaths.list_instances}
+            component={InstanceListPage}
+            onCreate={() => {
+              route(AdminPaths.new_instance);
+            }}
+            onUpdate={(id: string): void => {
+              route(`/instance/${id}/update`);
+            }}
+            setInstanceName={setInstanceName}
+            onUnauthorized={LoginPageAccessDenied}
+            onLoadError={ServerErrorRedirectTo(InstancePaths.error)}
+          />
+        )}
+        {admin && (
+          <Route
+            path={AdminPaths.new_instance}
+            component={InstanceCreatePage}
+            onBack={() => route(AdminPaths.list_instances)}
+            onConfirm={() => {
+              route(InstancePaths.order_list);
+            }}
+          />
+        )}
+        {admin && (
+          <Route
+            path={AdminPaths.update_instance}
+            component={AdminInstanceUpdatePage}
+            onBack={() => route(AdminPaths.list_instances)}
+            onConfirm={() => {
+              route(AdminPaths.list_instances);
+            }}
+            onUpdateError={ServerErrorRedirectTo(AdminPaths.list_instances)}
+            onLoadError={ServerErrorRedirectTo(AdminPaths.list_instances)}
+            onNotFound={NotFoundPage}
+          />
+        )}
+        {/**
+         * Update instance page
+         */}
+        <Route
+          path={InstancePaths.settings}
+          component={InstanceUpdatePage}
+          onBack={() => {
+            route(`/`);
+          }}
+          onConfirm={() => {
+            route(`/`);
+          }}
+          onUpdateError={noop}
+          onNotFound={IfAdminCreateDefaultOr(NotFoundPage)}
+          onUnauthorized={LoginPageAccessDenied}
+          onLoadError={ServerErrorRedirectTo(InstancePaths.error)}
+        />
+        {/**
+         * Update instance page
+         */}
+        <Route
+          path={InstancePaths.token}
+          component={TokenPage}
+          onChange={() => {
+            route(`/`);
+          }}
+          onCancel={() => {
+            route(InstancePaths.order_list)
+          }}
+          onNotFound={IfAdminCreateDefaultOr(NotFoundPage)}
+          onUnauthorized={LoginPageAccessDenied}
+          onLoadError={ServerErrorRedirectTo(InstancePaths.error)}
+        />
+        {/**
+         * Inventory pages
+         */}
+        <Route
+          path={InstancePaths.inventory_list}
+          component={ProductListPage}
+          onUnauthorized={LoginPageAccessDenied}
+          onLoadError={ServerErrorRedirectTo(InstancePaths.settings)}
+          onCreate={() => {
+            route(InstancePaths.inventory_new);
+          }}
+          onSelect={(id: string) => {
+            route(InstancePaths.inventory_update.replace(":pid", id));
+          }}
+          onNotFound={IfAdminCreateDefaultOr(NotFoundPage)}
+        />
+        <Route
+          path={InstancePaths.inventory_update}
+          component={ProductUpdatePage}
+          onUnauthorized={LoginPageAccessDenied}
+          onLoadError={ServerErrorRedirectTo(InstancePaths.inventory_list)}
+          onConfirm={() => {
+            route(InstancePaths.inventory_list);
+          }}
+          onBack={() => {
+            route(InstancePaths.inventory_list);
+          }}
+          onNotFound={IfAdminCreateDefaultOr(NotFoundPage)}
+        />
+        <Route
+          path={InstancePaths.inventory_new}
+          component={ProductCreatePage}
+          onConfirm={() => {
+            route(InstancePaths.inventory_list);
+          }}
+          onBack={() => {
+            route(InstancePaths.inventory_list);
+          }}
+        />
+        {/**
+         * Deposit confirmation pages
+         */}
+        <Route
+          path={InstancePaths.deposit_confirmation_list}
+          component={DepositConfirmationListPage}
+          onUnauthorized={LoginPageAccessDenied}
+          onLoadError={ServerErrorRedirectTo(InstancePaths.settings)}
+          onCreate={() => {
+            route(InstancePaths.deposit_confirmation_new);
+          }}
+          onSelect={(id: string) => {
+            route(InstancePaths.deposit_confirmation_update.replace(":pid", 
id));
+          }}
+          onNotFound={IfAdminCreateDefaultOr(NotFoundPage)}
+        />
+        <Route
+          path={InstancePaths.deposit_confirmation_update}
+          component={DepositConfirmationUpdatePage}
+          onUnauthorized={LoginPageAccessDenied}
+          
onLoadError={ServerErrorRedirectTo(InstancePaths.deposit_confirmation_list)}
+          onConfirm={() => {
+            route(InstancePaths.deposit_confirmation_list);
+          }}
+          onBack={() => {
+            route(InstancePaths.deposit_confirmation_list);
+          }}
+          onNotFound={IfAdminCreateDefaultOr(NotFoundPage)}
+        />
+        <Route
+          path={InstancePaths.deposit_confirmation_new}
+          component={DepositConfirmationCreatePage}
+          onConfirm={() => {
+            route(InstancePaths.deposit_confirmation_list);
+          }}
+          onBack={() => {
+            route(InstancePaths.deposit_confirmation_list);
+          }}
+        />
+        {/**
+         * Bank pages
+         */}
+        <Route
+          path={InstancePaths.bank_list}
+          component={BankAccountListPage}
+          onUnauthorized={LoginPageAccessDenied}
+          onLoadError={ServerErrorRedirectTo(InstancePaths.settings)}
+          onCreate={() => {
+            route(InstancePaths.bank_new);
+          }}
+          onSelect={(id: string) => {
+            route(InstancePaths.bank_update.replace(":bid", id));
+          }}
+          onNotFound={IfAdminCreateDefaultOr(NotFoundPage)}
+        />
+        <Route
+          path={InstancePaths.bank_update}
+          component={BankAccountUpdatePage}
+          onUnauthorized={LoginPageAccessDenied}
+          onLoadError={ServerErrorRedirectTo(InstancePaths.inventory_list)}
+          onConfirm={() => {
+            route(InstancePaths.bank_list);
+          }}
+          onBack={() => {
+            route(InstancePaths.bank_list);
+          }}
+          onNotFound={IfAdminCreateDefaultOr(NotFoundPage)}
+        />
+        <Route
+          path={InstancePaths.bank_new}
+          component={BankAccountCreatePage}
+          onConfirm={() => {
+            route(InstancePaths.bank_list);
+          }}
+          onBack={() => {
+            route(InstancePaths.bank_list);
+          }}
+        />
+        {/**
+         * Order pages
+         */}
+        <Route
+          path={InstancePaths.order_list}
+          component={OrderListPage}
+          onCreate={() => {
+            route(InstancePaths.order_new);
+          }}
+          onSelect={(id: string) => {
+            route(InstancePaths.order_details.replace(":oid", id));
+          }}
+          onUnauthorized={LoginPageAccessDenied}
+          onLoadError={ServerErrorRedirectTo(InstancePaths.settings)}
+          onNotFound={IfAdminCreateDefaultOr(NotFoundPage)}
+        />
+        <Route
+          path={InstancePaths.order_details}
+          component={OrderDetailsPage}
+          onUnauthorized={LoginPageAccessDenied}
+          onLoadError={ServerErrorRedirectTo(InstancePaths.order_list)}
+          onNotFound={IfAdminCreateDefaultOr(NotFoundPage)}
+          onBack={() => {
+            route(InstancePaths.order_list);
+          }}
+        />
+        <Route
+          path={InstancePaths.order_new}
+          component={OrderCreatePage}
+          onConfirm={(orderId: string) => {
+            route(InstancePaths.order_details.replace(":oid", orderId));
+          }}
+          onBack={() => {
+            route(InstancePaths.order_list);
+          }}
+        />
+        {/**
+         * Transfer pages
+         */}
+        <Route
+          path={InstancePaths.transfers_list}
+          component={TransferListPage}
+          onUnauthorized={LoginPageAccessDenied}
+          onNotFound={IfAdminCreateDefaultOr(NotFoundPage)}
+          onLoadError={ServerErrorRedirectTo(InstancePaths.settings)}
+          onCreate={() => {
+            route(InstancePaths.transfers_new);
+          }}
+        />
+        <Route
+          path={InstancePaths.transfers_new}
+          component={TransferCreatePage}
+          onConfirm={() => {
+            route(InstancePaths.transfers_list);
+          }}
+          onBack={() => {
+            route(InstancePaths.transfers_list);
+          }}
+        />
+        {/**
+         * Webhooks pages
+         */}
+        <Route
+          path={InstancePaths.webhooks_list}
+          component={WebhookListPage}
+          onUnauthorized={LoginPageAccessDenied}
+          onNotFound={IfAdminCreateDefaultOr(NotFoundPage)}
+          onLoadError={ServerErrorRedirectTo(InstancePaths.settings)}
+          onCreate={() => {
+            route(InstancePaths.webhooks_new);
+          }}
+          onSelect={(id: string) => {
+            route(InstancePaths.webhooks_update.replace(":tid", id));
+          }}
+        />
+        <Route
+          path={InstancePaths.webhooks_update}
+          component={WebhookUpdatePage}
+          onConfirm={() => {
+            route(InstancePaths.webhooks_list);
+          }}
+          onUnauthorized={LoginPageAccessDenied}
+          onLoadError={ServerErrorRedirectTo(InstancePaths.webhooks_list)}
+          onNotFound={IfAdminCreateDefaultOr(NotFoundPage)}
+          onBack={() => {
+            route(InstancePaths.webhooks_list);
+          }}
+        />
+        <Route
+          path={InstancePaths.webhooks_new}
+          component={WebhookCreatePage}
+          onConfirm={() => {
+            route(InstancePaths.webhooks_list);
+          }}
+          onBack={() => {
+            route(InstancePaths.webhooks_list);
+          }}
+        />
+        {/**
+         * Validator pages
+         */}
+        <Route
+          path={InstancePaths.otp_devices_list}
+          component={ValidatorListPage}
+          onUnauthorized={LoginPageAccessDenied}
+          onNotFound={IfAdminCreateDefaultOr(NotFoundPage)}
+          onLoadError={ServerErrorRedirectTo(InstancePaths.settings)}
+          onCreate={() => {
+            route(InstancePaths.otp_devices_new);
+          }}
+          onSelect={(id: string) => {
+            route(InstancePaths.otp_devices_update.replace(":vid", id));
+          }}
+        />
+        <Route
+          path={InstancePaths.otp_devices_update}
+          component={ValidatorUpdatePage}
+          onConfirm={() => {
+            route(InstancePaths.otp_devices_list);
+          }}
+          onUnauthorized={LoginPageAccessDenied}
+          onLoadError={ServerErrorRedirectTo(InstancePaths.otp_devices_list)}
+          onNotFound={IfAdminCreateDefaultOr(NotFoundPage)}
+          onBack={() => {
+            route(InstancePaths.otp_devices_list);
+          }}
+        />
+        <Route
+          path={InstancePaths.otp_devices_new}
+          component={ValidatorCreatePage}
+          onConfirm={() => {
+            route(InstancePaths.otp_devices_list);
+          }}
+          onBack={() => {
+            route(InstancePaths.otp_devices_list);
+          }}
+        />
+        {/**
+         * Templates pages
+         */}
+        <Route
+          path={InstancePaths.templates_list}
+          component={TemplateListPage}
+          onUnauthorized={LoginPageAccessDenied}
+          onNotFound={IfAdminCreateDefaultOr(NotFoundPage)}
+          onLoadError={ServerErrorRedirectTo(InstancePaths.settings)}
+          onCreate={() => {
+            route(InstancePaths.templates_new);
+          }}
+          onNewOrder={(id: string) => {
+            route(InstancePaths.templates_use.replace(":tid", id));
+          }}
+          onQR={(id: string) => {
+            route(InstancePaths.templates_qr.replace(":tid", id));
+          }}
+          onSelect={(id: string) => {
+            route(InstancePaths.templates_update.replace(":tid", id));
+          }}
+        />
+        <Route
+          path={InstancePaths.templates_update}
+          component={TemplateUpdatePage}
+          onConfirm={() => {
+            route(InstancePaths.templates_list);
+          }}
+          onUnauthorized={LoginPageAccessDenied}
+          onLoadError={ServerErrorRedirectTo(InstancePaths.templates_list)}
+          onNotFound={IfAdminCreateDefaultOr(NotFoundPage)}
+          onBack={() => {
+            route(InstancePaths.templates_list);
+          }}
+        />
+        <Route
+          path={InstancePaths.templates_new}
+          component={TemplateCreatePage}
+          onConfirm={() => {
+            route(InstancePaths.templates_list);
+          }}
+          onBack={() => {
+            route(InstancePaths.templates_list);
+          }}
+        />
+        <Route
+          path={InstancePaths.templates_use}
+          component={TemplateUsePage}
+          onOrderCreated={(id: string) => {
+            route(InstancePaths.order_details.replace(":oid", id));
+          }}
+          onUnauthorized={LoginPageAccessDenied}
+          onLoadError={ServerErrorRedirectTo(InstancePaths.templates_list)}
+          onNotFound={IfAdminCreateDefaultOr(NotFoundPage)}
+          onBack={() => {
+            route(InstancePaths.templates_list);
+          }}
+        />
+        <Route
+          path={InstancePaths.templates_qr}
+          component={TemplateQrPage}
+          onUnauthorized={LoginPageAccessDenied}
+          onLoadError={ServerErrorRedirectTo(InstancePaths.templates_list)}
+          onNotFound={IfAdminCreateDefaultOr(NotFoundPage)}
+          onBack={() => {
+            route(InstancePaths.templates_list);
+          }}
+        />
+
+        {/**
+         * reserves pages
+         */}
+        <Route
+          path={InstancePaths.reserves_list}
+          component={ReservesListPage}
+          onUnauthorized={LoginPageAccessDenied}
+          onNotFound={IfAdminCreateDefaultOr(NotFoundPage)}
+          onLoadError={ServerErrorRedirectTo(InstancePaths.settings)}
+          onSelect={(id: string) => {
+            route(InstancePaths.reserves_details.replace(":rid", id));
+          }}
+          onCreate={() => {
+            route(InstancePaths.reserves_new);
+          }}
+        />
+        <Route
+          path={InstancePaths.reserves_details}
+          component={ReservesDetailsPage}
+          onUnauthorized={LoginPageAccessDenied}
+          onLoadError={ServerErrorRedirectTo(InstancePaths.reserves_list)}
+          onNotFound={IfAdminCreateDefaultOr(NotFoundPage)}
+          onBack={() => {
+            route(InstancePaths.reserves_list);
+          }}
+        />
+        <Route
+          path={InstancePaths.reserves_new}
+          component={ReservesCreatePage}
+          onConfirm={() => {
+            route(InstancePaths.reserves_list);
+          }}
+          onBack={() => {
+            route(InstancePaths.reserves_list);
+          }}
+        />
+        <Route path={InstancePaths.kyc} component={ListKYCPage} />
+        <Route path={InstancePaths.interface} component={Settings} />
+        {/**
+         * Example pages
+         */}
+        <Route path="/loading" component={Loading} />
+        <Route default component={NotFoundPage} />
+      </Router>
+    </InstanceContextProvider>
+  );
+}
+
+export function Redirect({ to }: { to: string }): null {
+  useEffect(() => {
+    route(to, true);
+  });
+  return null;
+}
+
+function AdminInstanceUpdatePage({
+  id,
+  ...rest
+}: { id: string } & InstanceUpdatePageProps): VNode {
+  const [token, changeToken] = useBackendInstanceToken(id);
+  const updateLoginStatus = (token?: LoginToken): void => {
+    changeToken(token);
+  };
+  const value = useMemo(
+    () => ({ id, token, admin: true, changeToken }),
+    [id, token],
+  );
+  const { i18n } = useTranslationContext();
+
+  return (
+    <InstanceContextProvider value={value}>
+      <InstanceAdminUpdatePage
+        {...rest}
+        instanceId={id}
+        onLoadError={(error: HttpError<MerchantBackend.ErrorDetail>) => {
+          const notif =
+            error.type === ErrorType.TIMEOUT
+              ? {
+                message: i18n.str`The request to the backend take too long and 
was cancelled`,
+                description: i18n.str`Diagnostic from ${error.info.url} is 
'${error.message}'`,
+                type: "ERROR" as const,
+              }
+              : {
+                message: i18n.str`The backend reported a problem: HTTP status 
#${error.status}`,
+                description: i18n.str`Diagnostic from ${error.info.url} is 
'${error.message}'`,
+                details:
+                  error.type === ErrorType.CLIENT ||
+                    error.type === ErrorType.SERVER
+                    ? error.payload.detail
+                    : undefined,
+                type: "ERROR" as const,
+              };
+          return (
+            <Fragment>
+              <NotificationCard notification={notif} />
+              <LoginPage onConfirm={updateLoginStatus} />
+            </Fragment>
+          );
+        }}
+        onUnauthorized={() => {
+          return (
+            <Fragment>
+              <NotificationCard
+                notification={{
+                  message: i18n.str`Access denied`,
+                  description: i18n.str`The access token provided is invalid`,
+                  type: "ERROR",
+                }}
+              />
+              <LoginPage onConfirm={updateLoginStatus} />
+            </Fragment>
+          );
+        }}
+      />
+    </InstanceContextProvider>
+  );
+}
+
+function KycBanner(): VNode {
+  const kycStatus = useInstanceKYCDetails();
+  const { i18n } = useTranslationContext();
+  const [settings] = useSettings();
+  const today = format(new Date(), dateFormatForSettings(settings));
+  const [lastHide, setLastHide] = useSimpleLocalStorage("kyc-last-hide");
+  const hasBeenHidden = today === lastHide;
+  const needsToBeShown = kycStatus.ok && kycStatus.data.type === "redirect";
+  if (hasBeenHidden || !needsToBeShown) return <Fragment />;
+  return (
+    <NotificationCard
+      notification={{
+        type: "WARN",
+        message: "KYC verification needed",
+        description: (
+          <div>
+            <p>
+              Some transfer are on hold until a KYC process is completed. Go to
+              the KYC section in the left panel for more information
+            </p>
+            <div class="buttons is-right">
+              <button class="button" onClick={() => setLastHide(today)}>
+                <i18n.Translate>Hide for today</i18n.Translate>
+              </button>
+            </div>
+          </div>
+        ),
+      }}
+    />
+  );
+}
diff --git a/packages/auditor-backoffice-ui/src/assets/empty.png 
b/packages/auditor-backoffice-ui/src/assets/empty.png
new file mode 100644
index 000000000..5120d3138
Binary files /dev/null and 
b/packages/auditor-backoffice-ui/src/assets/empty.png differ
diff --git 
a/packages/auditor-backoffice-ui/src/assets/icons/android-chrome-192x192.png 
b/packages/auditor-backoffice-ui/src/assets/icons/android-chrome-192x192.png
new file mode 100644
index 000000000..93ebe2e2c
Binary files /dev/null and 
b/packages/auditor-backoffice-ui/src/assets/icons/android-chrome-192x192.png 
differ
diff --git 
a/packages/auditor-backoffice-ui/src/assets/icons/android-chrome-512x512.png 
b/packages/auditor-backoffice-ui/src/assets/icons/android-chrome-512x512.png
new file mode 100644
index 000000000..52d1623ea
Binary files /dev/null and 
b/packages/auditor-backoffice-ui/src/assets/icons/android-chrome-512x512.png 
differ
diff --git 
a/packages/auditor-backoffice-ui/src/assets/icons/apple-touch-icon.png 
b/packages/auditor-backoffice-ui/src/assets/icons/apple-touch-icon.png
new file mode 100644
index 000000000..254e4bb4d
Binary files /dev/null and 
b/packages/auditor-backoffice-ui/src/assets/icons/apple-touch-icon.png differ
diff --git a/packages/auditor-backoffice-ui/src/assets/icons/favicon-16x16.png 
b/packages/auditor-backoffice-ui/src/assets/icons/favicon-16x16.png
new file mode 100644
index 000000000..e81177dcb
Binary files /dev/null and 
b/packages/auditor-backoffice-ui/src/assets/icons/favicon-16x16.png differ
diff --git a/packages/auditor-backoffice-ui/src/assets/icons/favicon-32x32.png 
b/packages/auditor-backoffice-ui/src/assets/icons/favicon-32x32.png
new file mode 100644
index 000000000..40e9b5b47
Binary files /dev/null and 
b/packages/auditor-backoffice-ui/src/assets/icons/favicon-32x32.png differ
diff --git a/packages/auditor-backoffice-ui/src/assets/icons/languageicon.svg 
b/packages/auditor-backoffice-ui/src/assets/icons/languageicon.svg
new file mode 100644
index 000000000..22d58da65
--- /dev/null
+++ b/packages/auditor-backoffice-ui/src/assets/icons/languageicon.svg
@@ -0,0 +1,48 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Generator: Adobe Illustrator 19.1.0, SVG Export Plug-In . SVG Version: 
6.00 Build 0)  -->
+<svg version="1.1" xmlns="http://www.w3.org/2000/svg"; 
xmlns:xlink="http://www.w3.org/1999/xlink"; x="0px" y="0px"
+        viewBox="0 0 2411.2 2794" style="enable-background:new 0 0 2411.2 
2794;" xml:space="preserve">
+<style type="text/css">
+       .st0{fill:#FFFFFF;}
+       .st1{fill-rule:evenodd;clip-rule:evenodd;}
+       .st2{fill-rule:evenodd;clip-rule:evenodd;fill:#FFFFFF;}
+</style>
+<g id="Layer_2">
+</g>
+<g id="Layer_x5F_1_x5F_1">
+       <g>
+               <polygon points="1204.6,359.2 271.8,30 271.8,2060.1 
1204.6,1758.3               "/>
+               <polygon class="st0" points="1182.2,358.1 2150.6,29 2150.6,2059 
1182.2,1757.3           "/>
+               <polygon class="st0" points="30,2415.4 1182.2,2031.4 
1182.2,357.9 30,742                "/>
+               <polygon points="1707.2,2440.7 1870.5,2709.4 1956.6,2459.8      
        "/>
+               <g>
+                       <path 
d="M421.7,934.8c-6.1-6,8,49.1,27.6,68.9c34.8,35.1,61.9,39.6,76.4,40.2c32,1.3,71.5-8,94.9-17.8
+                               
c22.7-9.7,62.4-30,77.5-59.6c3.2-6.3,11.9-17,6.4-43.2c-4.2-20.2-17-27.3-32.7-26.2c-15.7,1.1-63.2,13.7-86.1,20.8
+                               
c-23,7-70.3,21.4-90.9,25.8C474.3,948.2,429,941.7,421.7,934.8z"/>
+                       <path 
d="M1003.1,1593.7c-9.1-3.3-196.9-81.1-223.6-93.9c-21.8-10.5-75.2-33.1-100.4-43.3c70.8-109.2,115.5-191.6,121.5-204.1
+                               
c11-23,86-169.6,87.7-178.7c1.7-9.1,3.8-42.9,2.2-51c-1.7-8.2-29.1,7.6-66.4,20.2c-37.4,12.6-108.4,58.8-135.8,64.6
+                               
c-27.5,5.7-115.5,39.1-160.5,54c-45,14.9-130.2,40.9-165.2,50.4c-35.1,9.5-65.7,10.2-85.3,16.2c0,0,2.6,27.5,7.8,35.7
+                               
c5.2,8.2,23.7,28.4,45.3,34.1c21.6,5.7,57.3,3.4,73.6-0.3c16.3-3.8,44.4-17.5,48.2-23.6c3.8-6.1-2-24.9,4.5-30.6
+                               
c6.5-5.6,92.2-25.7,124.6-35.4c32.4-10,156.3-52.6,173.1-50.5c-5.3,17.7-105,215.1-137.1,274c-32.1,58.9-218.6,318-258.3,363.6
+                               
c-30.1,34.7-103.2,123.5-128.5,143.6c6.4,1.8,51.6-2.1,59.9-7.2c51.3-31.6,136.9-138.1,164.4-170.5
+                               
c81.9-96,153.8-196.8,210.8-283.4h0.1c11.1,4.6,100.9,77.8,124.4,94c23.4,16.2,115.9,67.8,136,76.4c20,8.7,97.1,44.2,100.3,32.2
+                               C1029.4,1668,1012.2,1597.1,1003.1,1593.7z"/>
+               </g>
+               <path class="st1" 
d="M569,2572c18,11,35,20,54,29c38,19,81,39,122,54c56,21,112,38,168,51c31,7,65,13,98,18c3,0,92,11,110,11h90
+                       
c35-3,68-5,103-10c28-4,59-9,89-16c22-5,45-10,67-17c21-6,45-14,68-22c15-5,31-12,47-18c13-6,29-13,44-19c18-8,39-19,59-29
+                       
c16-8,34-18,51-28c13-7,43-30,59-30c18,0,30,16,30,30c0,29-39,38-57,51c-19,13-42,23-62,34c-40,21-81,39-120,54
+                       
c-51,19-107,37-157,49c-19,4-38,9-57,12c-10,2-114,18-143,18h-132c-35-3-72-7-107-12c-31-5-64-11-95-18c-24-5-50-12-73-19
+                       
c-40-11-79-25-117-40c-69-26-141-60-209-105c-12-8-13-16-13-25c0-15,11-29,29-29C531,2546,563,2569,569,2572z"/>
+               <path class="st1" d="M1151,2009L61,2372V764l1090-363V2009z 
M1212,354v1680c-1,5-3,10-7,15c-2,3-6,7-9,8c-25,10-1151,388-1166,388
+                       
c-12,0-23-8-29-21c0-1-1-2-1-4V739c2-5,3-12,7-16c8-11,22-13,31-16c17-6,1126-378,1142-378C1190,329,1212,336,1212,354z"/>
+               <path class="st1" d="M2120,2017l-907-282V380l907-308V2017z 
M2181,32v2023c-1,23-17,33-32,33c-13,0-107-32-123-37
+                       
c-126-39-253-78-378-117c-28-9-57-18-84-27c-24-7-50-15-74-23c-107-33-216-66-323-102c-4-1-14-15-14-18V351c2-5,4-11,9-15
+                       
c8-9,351-123,486-168c36-13,487-168,501-168C2167,0,2181,13,2181,32z"/>
+               <polygon points="2411.2,2440.7 1199.5,2054.5 1204.6,373.2 
2411.2,757.2          "/>
+               <g>
+                       <path class="st2" 
d="M1800.3,1124.6L1681.4,1412l218.6,66.3L1800.3,1124.6z 
M1729,853.2l156.1,47.3l284.4,1025l-160.3-48.7
+                               
l-57.6-210.4L1620.2,1566l-71.3,171.4l-160.4-48.7L1729,853.2z"/>
+               </g>
+       </g>
+</g>
+</svg>
diff --git a/packages/auditor-backoffice-ui/src/assets/icons/mstile-150x150.png 
b/packages/auditor-backoffice-ui/src/assets/icons/mstile-150x150.png
new file mode 100644
index 000000000..9cfb889be
Binary files /dev/null and 
b/packages/auditor-backoffice-ui/src/assets/icons/mstile-150x150.png differ
diff --git a/packages/auditor-backoffice-ui/src/assets/logo-2021.svg 
b/packages/auditor-backoffice-ui/src/assets/logo-2021.svg
new file mode 100644
index 000000000..8c5ff3e5b
--- /dev/null
+++ b/packages/auditor-backoffice-ui/src/assets/logo-2021.svg
@@ -0,0 +1,9 @@
+<?xml version="1.0" encoding="UTF-8" standalone="no"?>
+<svg xmlns="http://www.w3.org/2000/svg"; viewBox="0 0 201 90">
+  <g fill="#0042b3" fill-rule="evenodd" stroke-width=".3">
+    <path d="M86.7 1.1c15.6 0 29 9.4 36 23.2h-5.9A35.1 35.1 0 0086.7 6.5C67 
6.5 51 23.6 51 44.7c0 10.4 3.8 19.7 10 26.6a31.4 31.4 0 01-4.2 3A45.2 45.2 0 
0146 44.7c0-24 18.2-43.6 40.7-43.6zm35.8 64.3a40.4 40.4 0 01-39 22.8c3-1.5 
6-3.5 8.6-5.7a35.6 35.6 0 0024.6-17.1z" />
+    <path d="M64.2 1.1l3.1.1c-3 1.6-5.9 3.5-8.5 5.8a37.5 37.5 0 00-30.2 37.7c0 
14.3 7.3 26.7 18 33.3a29.6 29.6 0 01-8.5.2c-9-8-14.6-20-14.6-33.5 0-24 
18.2-43.6 40.7-43.6zm5.4 81.4a35.6 35.6 0 0024.6-17.1h5.9a40.4 40.4 0 01-39 
22.8c3-1.5 5.9-3.5 8.5-5.7zm24.8-58.2a37 37 0 00-12.6-12.8 29.6 29.6 0 
018.5-.2c4 3.6 7.4 8 9.9 13z" />
+    <path d="M41.8 1.1c1 0 2 0 3.1.2-3 1.5-5.9 3.4-8.5 5.6A37.5 37.5 0 006.1 
44.7c0 21.1 16 38.3 35.7 38.3 12.6 0 23.6-7 30-17.6h5.8a40.4 40.4 0 01-35.8 
23C19.3 88.4 1 68.8 1 44.7c0-24 18.2-43.6 40.7-43.6zm30.1 23.2a38.1 38.1 0 
00-4.5-6.1c1.3-1.2 2.7-2.2 4.3-3 2.3 2.7 4.4 5.8 6 9.1z" />
+  </g>
+  <path d="M76.1 34.4h9.2v-5H61.9v5H71v26h5.1zM92.6 52.9h13.7l3 
7.4h5.3l-12.7-31.2h-4.7L84.5 60.3h5.2zm11.8-4.9h-9.9l5-12.4zM123.8 
29.4h-4.6v31h20.6v-5h-16zM166.5 
29.4H145v31h21.6v-5H150v-8.3h14.5v-4.9h-14.5v-8h16.4zM191.2 39.5c0 1.6-.5 
2.8-1.6 3.8s-2.6 1.4-4.4 1.4h-7.4V34.3h7.4c1.9 0 3.4.4 4.4 1.3 1 .9 1.6 2.2 1.6 
3.9zm6 20.8l-7.7-11.7c1-.3 1.9-.7 2.7-1.3a8.8 8.8 0 003.6-4.6c.4-1 .5-2.2.5-3.5 
0-1.5-.2-2.9-.7-4.1a8.4 8.4 0 
00-2.1-3.1c-1-.8-2-1.5-3.4-2-1.3-.4-2.8-.6-4.5-.6h-12.9v31h5V49.4 [...]
+</svg>
\ No newline at end of file
diff --git a/packages/auditor-backoffice-ui/src/assets/logo.jpeg 
b/packages/auditor-backoffice-ui/src/assets/logo.jpeg
new file mode 100644
index 000000000..489832f7c
Binary files /dev/null and 
b/packages/auditor-backoffice-ui/src/assets/logo.jpeg differ
diff --git 
a/packages/auditor-backoffice-ui/src/components/exception/AsyncButton.tsx 
b/packages/auditor-backoffice-ui/src/components/exception/AsyncButton.tsx
new file mode 100644
index 000000000..b1fc33877
--- /dev/null
+++ b/packages/auditor-backoffice-ui/src/components/exception/AsyncButton.tsx
@@ -0,0 +1,55 @@
+/*
+ This file is part of GNU Taler
+ (C) 2021-2023 Taler Systems S.A.
+
+ GNU Taler is free software; you can redistribute it and/or modify it under the
+ terms of the GNU General Public License as published by the Free Software
+ Foundation; either version 3, or (at your option) any later version.
+
+ GNU Taler is distributed in the hope that it will be useful, but WITHOUT ANY
+ WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
+ A PARTICULAR PURPOSE.  See the GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License along with
+ GNU Taler; see the file COPYING.  If not, see <http://www.gnu.org/licenses/>
+ */
+
+/**
+ *
+ * @author Sebastian Javier Marchano (sebasjm)
+ */
+
+import { ComponentChildren, h } from "preact";
+import { LoadingModal } from "../modal/index.js";
+import { useAsync } from "../../hooks/async.js";
+import { useTranslationContext } from "@gnu-taler/web-util/browser";
+
+type Props = {
+  children: ComponentChildren;
+  disabled: boolean;
+  onClick?: () => Promise<void>;
+  [rest: string]: any;
+};
+
+export function AsyncButton({ onClick, disabled, children, ...rest }: Props) {
+  const { isSlow, isLoading, request, cancel } = useAsync(onClick);
+  const { i18n } = useTranslationContext();
+  if (isSlow) {
+    return <LoadingModal onCancel={cancel} />;
+  }
+  if (isLoading) {
+    return (
+      <button class="button">
+        <i18n.Translate>Loading...</i18n.Translate>
+      </button>
+    );
+  }
+
+  return (
+    <span {...rest}>
+      <button class="button is-success" onClick={request} disabled={disabled}>
+        {children}
+      </button>
+    </span>
+  );
+}
diff --git a/packages/auditor-backoffice-ui/src/components/exception/QR.tsx 
b/packages/auditor-backoffice-ui/src/components/exception/QR.tsx
new file mode 100644
index 000000000..c9340ea76
--- /dev/null
+++ b/packages/auditor-backoffice-ui/src/components/exception/QR.tsx
@@ -0,0 +1,49 @@
+/*
+ This file is part of GNU Taler
+ (C) 2021-2023 Taler Systems S.A.
+
+ GNU Taler is free software; you can redistribute it and/or modify it under the
+ terms of the GNU General Public License as published by the Free Software
+ Foundation; either version 3, or (at your option) any later version.
+
+ GNU Taler is distributed in the hope that it will be useful, but WITHOUT ANY
+ WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
+ A PARTICULAR PURPOSE.  See the GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License along with
+ GNU Taler; see the file COPYING.  If not, see <http://www.gnu.org/licenses/>
+ */
+
+import { h, VNode } from "preact";
+import { useEffect, useRef } from "preact/hooks";
+import qrcode from "qrcode-generator";
+
+export function QR({ text }: { text: string }): VNode {
+  const divRef = useRef<HTMLDivElement>(null);
+  useEffect(() => {
+    const qr = qrcode(0, "L");
+    qr.addData(text);
+    qr.make();
+    if (divRef.current) {
+      divRef.current.innerHTML = qr.createSvgTag({
+        scalable: true,
+      });
+    }
+  });
+
+  return (
+    <div
+      style={{
+        width: "100%",
+        display: "flex",
+        flexDirection: "column",
+        alignItems: "center",
+      }}
+    >
+      <div
+        style={{ width: "50%", minWidth: 200, maxWidth: 300 }}
+        ref={divRef}
+      />
+    </div>
+  );
+}
diff --git 
a/packages/auditor-backoffice-ui/src/components/exception/loading.tsx 
b/packages/auditor-backoffice-ui/src/components/exception/loading.tsx
new file mode 100644
index 000000000..a043b81eb
--- /dev/null
+++ b/packages/auditor-backoffice-ui/src/components/exception/loading.tsx
@@ -0,0 +1,48 @@
+/*
+ This file is part of GNU Taler
+ (C) 2021-2023 Taler Systems S.A.
+
+ GNU Taler is free software; you can redistribute it and/or modify it under the
+ terms of the GNU General Public License as published by the Free Software
+ Foundation; either version 3, or (at your option) any later version.
+
+ GNU Taler is distributed in the hope that it will be useful, but WITHOUT ANY
+ WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
+ A PARTICULAR PURPOSE.  See the GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License along with
+ GNU Taler; see the file COPYING.  If not, see <http://www.gnu.org/licenses/>
+ */
+
+/**
+ *
+ * @author Sebastian Javier Marchano (sebasjm)
+ */
+
+import { h, VNode } from "preact";
+
+export function Loading(): VNode {
+  return (
+    <div
+      class="columns is-centered is-vcentered"
+      style={{
+        height: "calc(100% - 3rem)",
+        position: "absolute",
+        width: "100%",
+      }}
+    >
+      <Spinner />
+    </div>
+  );
+}
+
+export function Spinner(): VNode {
+  return (
+    <div class="lds-ring">
+      <div />
+      <div />
+      <div />
+      <div />
+    </div>
+  );
+}
diff --git 
a/packages/auditor-backoffice-ui/src/components/form/FormProvider.tsx 
b/packages/auditor-backoffice-ui/src/components/form/FormProvider.tsx
new file mode 100644
index 000000000..0d53c4d08
--- /dev/null
+++ b/packages/auditor-backoffice-ui/src/components/form/FormProvider.tsx
@@ -0,0 +1,109 @@
+/*
+ This file is part of GNU Taler
+ (C) 2021-2023 Taler Systems S.A.
+
+ GNU Taler is free software; you can redistribute it and/or modify it under the
+ terms of the GNU General Public License as published by the Free Software
+ Foundation; either version 3, or (at your option) any later version.
+
+ GNU Taler is distributed in the hope that it will be useful, but WITHOUT ANY
+ WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
+ A PARTICULAR PURPOSE.  See the GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License along with
+ GNU Taler; see the file COPYING.  If not, see <http://www.gnu.org/licenses/>
+ */
+
+/**
+ *
+ * @author Sebastian Javier Marchano (sebasjm)
+ */
+
+import { ComponentChildren, createContext, h, VNode } from "preact";
+import { useContext, useMemo } from "preact/hooks";
+
+type Updater<S> = (value: (prevState: S) => S) => void;
+
+export interface Props<T> {
+  object?: Partial<T>;
+  errors?: FormErrors<T>;
+  name?: string;
+  valueHandler: Updater<Partial<T>> | null;
+  children: ComponentChildren;
+}
+
+const noUpdater: Updater<Partial<unknown>> = () => (s: unknown) => s;
+
+export function FormProvider<T>({
+  object = {},
+  errors = {},
+  name = "",
+  valueHandler,
+  children,
+}: Props<T>): VNode {
+  const initialObject = useMemo(() => object, []);
+  const value = useMemo<FormType<T>>(
+    () => ({
+      errors,
+      object,
+      initialObject,
+      valueHandler: valueHandler ? valueHandler : noUpdater,
+      name,
+      toStr: {},
+      fromStr: {},
+    }),
+    [errors, object, valueHandler],
+  );
+
+  return (
+    <FormContext.Provider value={value}>
+      <form
+        class="field"
+        onSubmit={(e) => {
+          e.preventDefault();
+          // if (valueHandler) valueHandler(object);
+        }}
+      >
+        {children}
+      </form>
+    </FormContext.Provider>
+  );
+}
+
+export interface FormType<T> {
+  object: Partial<T>;
+  initialObject: Partial<T>;
+  errors: FormErrors<T>;
+  toStr: FormtoStr<T>;
+  name: string;
+  fromStr: FormfromStr<T>;
+  valueHandler: Updater<Partial<T>>;
+}
+
+const FormContext = createContext<FormType<unknown>>(null!);
+
+/**
+ * FIXME:
+ * USE MEMORY EVENTS INSTEAD OF CONTEXT
+ * @deprecated
+ */
+
+export function useFormContext<T>() {
+  return useContext<FormType<T>>(FormContext);
+}
+
+export type FormErrors<T> = {
+  [P in keyof T]?: string | FormErrors<T[P]>;
+};
+
+export type FormtoStr<T> = {
+  [P in keyof T]?: (f?: T[P]) => string;
+};
+
+export type FormfromStr<T> = {
+  [P in keyof T]?: (f: string) => T[P];
+};
+
+export type FormUpdater<T> = {
+  [P in keyof T]?: (f: keyof T) => (v: T[P]) => void;
+};
diff --git a/packages/auditor-backoffice-ui/src/components/form/Input.tsx 
b/packages/auditor-backoffice-ui/src/components/form/Input.tsx
new file mode 100644
index 000000000..c1ddcb064
--- /dev/null
+++ b/packages/auditor-backoffice-ui/src/components/form/Input.tsx
@@ -0,0 +1,116 @@
+/*
+ This file is part of GNU Taler
+ (C) 2021-2023 Taler Systems S.A.
+
+ GNU Taler is free software; you can redistribute it and/or modify it under the
+ terms of the GNU General Public License as published by the Free Software
+ Foundation; either version 3, or (at your option) any later version.
+
+ GNU Taler is distributed in the hope that it will be useful, but WITHOUT ANY
+ WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
+ A PARTICULAR PURPOSE.  See the GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License along with
+ GNU Taler; see the file COPYING.  If not, see <http://www.gnu.org/licenses/>
+ */
+
+/**
+ *
+ * @author Sebastian Javier Marchano (sebasjm)
+ */
+import { ComponentChildren, h, VNode } from "preact";
+import { useField, InputProps } from "./useField.js";
+
+interface Props<T> extends InputProps<T> {
+  inputType?: "text" | "number" | "multiline" | "password";
+  expand?: boolean;
+  toStr?: (v?: any) => string;
+  fromStr?: (s: string) => any;
+  inputExtra?: any;
+  side?: ComponentChildren;
+  children?: ComponentChildren;
+}
+
+const defaultToString = (f?: any): string => f || "";
+const defaultFromString = (v: string): any => v as any;
+
+const TextInput = ({ inputType, error, ...rest }: any) =>
+  inputType === "multiline" ? (
+    <textarea
+      {...rest}
+      class={error ? "textarea is-danger" : "textarea"}
+      rows="3"
+    />
+  ) : (
+    <input
+      {...rest}
+      class={error ? "input is-danger" : "input"}
+      type={inputType}
+    />
+  );
+
+export function Input<T>({
+  name,
+  readonly,
+  placeholder,
+  tooltip,
+  label,
+  expand,
+  help,
+  children,
+  inputType,
+  inputExtra,
+  side,
+  fromStr = defaultFromString,
+  toStr = defaultToString,
+}: Props<keyof T>): VNode {
+  const { error, value, onChange, required } = useField<T>(name);
+  return (
+    <div class="field is-horizontal">
+      <div class="field-label is-normal">
+        <label class="label">
+          {label}
+          {tooltip && (
+            <span class="icon has-tooltip-right" data-tooltip={tooltip}>
+              <i class="mdi mdi-information" />
+            </span>
+          )}
+        </label>
+      </div>
+      <div class="field-body is-flex-grow-3">
+        <div class="field">
+          <p
+            class={
+              expand
+                ? "control is-expanded has-icons-right"
+                : "control has-icons-right"
+            }
+          >
+            <TextInput
+              error={error}
+              {...inputExtra}
+              inputType={inputType}
+              placeholder={placeholder}
+              readonly={readonly}
+              disabled={readonly}
+              name={String(name)}
+              value={toStr(value)}
+              onChange={(e: h.JSX.TargetedEvent<HTMLInputElement>): void =>
+                onChange(fromStr(e.currentTarget.value))
+              }
+            />
+            {help}
+            {children}
+            {required && (
+              <span class="icon has-text-danger is-right">
+                <i class="mdi mdi-alert" />
+              </span>
+            )}
+          </p>
+          {error && <p class="help is-danger">{error}</p>}
+        </div>
+        {side}
+      </div>
+    </div>
+  );
+}
diff --git a/packages/auditor-backoffice-ui/src/components/form/InputArray.tsx 
b/packages/auditor-backoffice-ui/src/components/form/InputArray.tsx
new file mode 100644
index 000000000..4ed4c4b28
--- /dev/null
+++ b/packages/auditor-backoffice-ui/src/components/form/InputArray.tsx
@@ -0,0 +1,139 @@
+/*
+ This file is part of GNU Taler
+ (C) 2021-2023 Taler Systems S.A.
+
+ GNU Taler is free software; you can redistribute it and/or modify it under the
+ terms of the GNU General Public License as published by the Free Software
+ Foundation; either version 3, or (at your option) any later version.
+
+ GNU Taler is distributed in the hope that it will be useful, but WITHOUT ANY
+ WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
+ A PARTICULAR PURPOSE.  See the GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License along with
+ GNU Taler; see the file COPYING.  If not, see <http://www.gnu.org/licenses/>
+ */
+
+/**
+ *
+ * @author Sebastian Javier Marchano (sebasjm)
+ */
+import { useTranslationContext } from "@gnu-taler/web-util/browser";
+import { h, VNode } from "preact";
+import { useState } from "preact/hooks";
+import { InputProps, useField } from "./useField.js";
+
+export interface Props<T> extends InputProps<T> {
+  isValid?: (e: any) => boolean;
+  addonBefore?: string;
+  toStr?: (v?: any) => string;
+  fromStr?: (s: string) => any;
+}
+
+const defaultToString = (f?: any): string => f || "";
+const defaultFromString = (v: string): any => v as any;
+
+export function InputArray<T>({
+  name,
+  readonly,
+  placeholder,
+  tooltip,
+  label,
+  help,
+  addonBefore,
+  isValid = () => true,
+  fromStr = defaultFromString,
+  toStr = defaultToString,
+}: Props<keyof T>): VNode {
+  const { error: formError, value, onChange, required } = useField<T>(name);
+  const [localError, setLocalError] = useState<string | null>(null);
+
+  const error = localError || formError;
+
+  const array: any[] = (value ? value! : []) as any;
+  const [currentValue, setCurrentValue] = useState("");
+  const { i18n } = useTranslationContext();
+
+  return (
+    <div class="field is-horizontal">
+      <div class="field-label is-normal">
+        <label class="label">
+          {label}
+          {tooltip && (
+            <span class="icon has-tooltip-right" data-tooltip={tooltip}>
+              <i class="mdi mdi-information" />
+            </span>
+          )}
+        </label>
+      </div>
+      <div class="field-body is-flex-grow-3">
+        <div class="field">
+          <div class="field has-addons">
+            {addonBefore && (
+              <div class="control">
+                <a class="button is-static">{addonBefore}</a>
+              </div>
+            )}
+            <p class="control is-expanded has-icons-right">
+              <input
+                class={error ? "input is-danger" : "input"}
+                type="text"
+                placeholder={placeholder}
+                readonly={readonly}
+                disabled={readonly}
+                name={String(name)}
+                value={currentValue}
+                onChange={(e): void => setCurrentValue(e.currentTarget.value)}
+              />
+              {required && (
+                <span class="icon has-text-danger is-right">
+                  <i class="mdi mdi-alert" />
+                </span>
+              )}
+            </p>
+            <p class="control">
+              <button
+                class="button is-info has-tooltip-left"
+                disabled={!currentValue}
+                onClick={(): void => {
+                  const v = fromStr(currentValue);
+                  if (!isValid(v)) {
+                    setLocalError(
+                      i18n.str`The value ${v} is invalid for a payment url`,
+                    );
+                    return;
+                  }
+                  setLocalError(null);
+                  onChange([v, ...array] as any);
+                  setCurrentValue("");
+                }}
+                data-tooltip={i18n.str`add element to the list`}
+              >
+                <i18n.Translate>add</i18n.Translate>
+              </button>
+            </p>
+          </div>
+          {help}
+          {error && <p class="help is-danger"> {error} </p>}
+          {array.map((v, i) => (
+            <div key={i} class="tags has-addons mt-3 mb-0">
+              <span
+                class="tag is-medium is-info mb-0"
+                style={{ maxWidth: "90%" }}
+              >
+                {v}
+              </span>
+              <a
+                class="tag is-medium is-danger is-delete mb-0"
+                onClick={() => {
+                  onChange(array.filter((f) => f !== v) as any);
+                  setCurrentValue(toStr(v));
+                }}
+              />
+            </div>
+          ))}
+        </div>
+      </div>
+    </div>
+  );
+}
diff --git 
a/packages/auditor-backoffice-ui/src/components/form/InputBoolean.tsx 
b/packages/auditor-backoffice-ui/src/components/form/InputBoolean.tsx
new file mode 100644
index 000000000..f79e16c07
--- /dev/null
+++ b/packages/auditor-backoffice-ui/src/components/form/InputBoolean.tsx
@@ -0,0 +1,91 @@
+/*
+ This file is part of GNU Taler
+ (C) 2021-2023 Taler Systems S.A.
+
+ GNU Taler is free software; you can redistribute it and/or modify it under the
+ terms of the GNU General Public License as published by the Free Software
+ Foundation; either version 3, or (at your option) any later version.
+
+ GNU Taler is distributed in the hope that it will be useful, but WITHOUT ANY
+ WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
+ A PARTICULAR PURPOSE.  See the GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License along with
+ GNU Taler; see the file COPYING.  If not, see <http://www.gnu.org/licenses/>
+ */
+
+/**
+ *
+ * @author Sebastian Javier Marchano (sebasjm)
+ */
+import { h, VNode } from "preact";
+import { InputProps, useField } from "./useField.js";
+
+interface Props<T> extends InputProps<T> {
+  name: T;
+  readonly?: boolean;
+  expand?: boolean;
+  threeState?: boolean;
+  toBoolean?: (v?: any) => boolean | undefined;
+  fromBoolean?: (s: boolean | undefined) => any;
+}
+
+const defaultToBoolean = (f?: any): boolean | undefined => f || "";
+const defaultFromBoolean = (v: boolean | undefined): any => v as any;
+
+export function InputBoolean<T>({
+  name,
+  readonly,
+  placeholder,
+  tooltip,
+  label,
+  help,
+  threeState,
+  expand,
+  fromBoolean = defaultFromBoolean,
+  toBoolean = defaultToBoolean,
+}: Props<keyof T>): VNode {
+  const { error, value, onChange } = useField<T>(name);
+
+  const onCheckboxClick = (): void => {
+    const c = toBoolean(value);
+    if (c === false && threeState) return onChange(undefined as any);
+    return onChange(fromBoolean(!c));
+  };
+
+  return (
+    <div class="field is-horizontal">
+      <div class="field-label is-normal">
+        <label class="label">
+          {label}
+          {tooltip && (
+            <span class="icon has-tooltip-right" data-tooltip={tooltip}>
+              <i class="mdi mdi-information" />
+            </span>
+          )}
+        </label>
+      </div>
+      <div class="field-body is-flex-grow-3">
+        <div class="field">
+          <p class={expand ? "control is-expanded" : "control"}>
+            <label class="b-checkbox checkbox">
+              <input
+                type="checkbox"
+                class={toBoolean(value) === undefined ? "is-indeterminate" : 
""}
+                checked={toBoolean(value)}
+                placeholder={placeholder}
+                readonly={readonly}
+                name={String(name)}
+                disabled={readonly}
+                onChange={onCheckboxClick}
+              />
+              <span class="check" />
+            </label>
+            {help}
+          </p>
+          {error && <p class="help is-danger">{error}</p>}
+        </div>
+      </div>
+    </div>
+  );
+}
diff --git 
a/packages/auditor-backoffice-ui/src/components/form/InputCurrency.tsx 
b/packages/auditor-backoffice-ui/src/components/form/InputCurrency.tsx
new file mode 100644
index 000000000..b02354d7c
--- /dev/null
+++ b/packages/auditor-backoffice-ui/src/components/form/InputCurrency.tsx
@@ -0,0 +1,67 @@
+/*
+ This file is part of GNU Taler
+ (C) 2021-2023 Taler Systems S.A.
+
+ GNU Taler is free software; you can redistribute it and/or modify it under the
+ terms of the GNU General Public License as published by the Free Software
+ Foundation; either version 3, or (at your option) any later version.
+
+ GNU Taler is distributed in the hope that it will be useful, but WITHOUT ANY
+ WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
+ A PARTICULAR PURPOSE.  See the GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License along with
+ GNU Taler; see the file COPYING.  If not, see <http://www.gnu.org/licenses/>
+ */
+
+/**
+ *
+ * @author Sebastian Javier Marchano (sebasjm)
+ */
+import { ComponentChildren, h, VNode } from "preact";
+import { useConfigContext } from "../../context/config.js";
+import { Amount } from "../../declaration.js";
+import { InputWithAddon } from "./InputWithAddon.js";
+import { InputProps } from "./useField.js";
+
+export interface Props<T> extends InputProps<T> {
+  expand?: boolean;
+  addonAfter?: ComponentChildren;
+  children?: ComponentChildren;
+  side?: ComponentChildren;
+}
+
+export function InputCurrency<T>({
+  name,
+  readonly,
+  label,
+  placeholder,
+  help,
+  tooltip,
+  expand,
+  addonAfter,
+  children,
+  side,
+}: Props<keyof T>): VNode {
+  const config = useConfigContext();
+  return (
+    <InputWithAddon<T>
+      name={name}
+      readonly={readonly}
+      addonBefore={config.currency}
+      side={side}
+      label={label}
+      placeholder={placeholder}
+      help={help}
+      tooltip={tooltip}
+      addonAfter={addonAfter}
+      inputType="number"
+      expand={expand}
+      toStr={(v?: Amount) => v?.split(":")[1] || ""}
+      fromStr={(v: string) => (!v ? undefined : `${config.currency}:${v}`)}
+      inputExtra={{ min: 0 }}
+    >
+      {children}
+    </InputWithAddon>
+  );
+}
diff --git a/packages/auditor-backoffice-ui/src/components/form/InputDate.tsx 
b/packages/auditor-backoffice-ui/src/components/form/InputDate.tsx
new file mode 100644
index 000000000..a398629dc
--- /dev/null
+++ b/packages/auditor-backoffice-ui/src/components/form/InputDate.tsx
@@ -0,0 +1,164 @@
+/*
+ This file is part of GNU Taler
+ (C) 2021-2023 Taler Systems S.A.
+
+ GNU Taler is free software; you can redistribute it and/or modify it under the
+ terms of the GNU General Public License as published by the Free Software
+ Foundation; either version 3, or (at your option) any later version.
+
+ GNU Taler is distributed in the hope that it will be useful, but WITHOUT ANY
+ WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
+ A PARTICULAR PURPOSE.  See the GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License along with
+ GNU Taler; see the file COPYING.  If not, see <http://www.gnu.org/licenses/>
+ */
+
+/**
+ *
+ * @author Sebastian Javier Marchano (sebasjm)
+ */
+import { useTranslationContext } from "@gnu-taler/web-util/browser";
+import { format } from "date-fns";
+import { ComponentChildren, h, VNode } from "preact";
+import { useState } from "preact/hooks";
+import { DatePicker } from "../picker/DatePicker.js";
+import { InputProps, useField } from "./useField.js";
+import { dateFormatForSettings, useSettings } from 
"../../hooks/useSettings.js";
+
+export interface Props<T> extends InputProps<T> {
+  readonly?: boolean;
+  expand?: boolean;
+  //FIXME: create separated components InputDate and InputTimestamp
+  withTimestampSupport?: boolean;
+  side?: ComponentChildren;
+}
+
+export function InputDate<T>({
+  name,
+  readonly,
+  label,
+  placeholder,
+  help,
+  tooltip,
+  expand,
+  withTimestampSupport,
+  side,
+}: Props<keyof T>): VNode {
+  const [opened, setOpened] = useState(false);
+  const { i18n } = useTranslationContext();
+  const [settings] = useSettings()
+
+  const { error, required, value, onChange } = useField<T>(name);
+
+  let strValue = "";
+  if (!value) {
+    strValue = withTimestampSupport ? "unknown" : "";
+  } else if (value instanceof Date) {
+    strValue = format(value, dateFormatForSettings(settings));
+  } else if (value.t_s) {
+    strValue =
+      value.t_s === "never"
+        ? withTimestampSupport
+          ? "never"
+          : ""
+        : format(new Date(value.t_s * 1000), dateFormatForSettings(settings));
+  }
+
+  return (
+    <div class="field is-horizontal">
+      <div class="field-label is-normal">
+        <label class="label">
+          {label}
+          {tooltip && (
+            <span class="icon has-tooltip-right" data-tooltip={tooltip}>
+              <i class="mdi mdi-information" />
+            </span>
+          )}
+        </label>
+      </div>
+      <div class="field-body is-flex-grow-3">
+        <div class="field">
+          <div class="field has-addons">
+            <p
+              class={
+                expand
+                  ? "control is-expanded has-icons-right"
+                  : "control has-icons-right"
+              }
+            >
+              <input
+                class="input"
+                type="text"
+                readonly
+                value={strValue}
+                placeholder={placeholder}
+                onClick={() => {
+                  if (!readonly) setOpened(true);
+                }}
+              />
+              {required && (
+                <span class="icon has-text-danger is-right">
+                  <i class="mdi mdi-alert" />
+                </span>
+              )}
+              {help}
+            </p>
+            <div
+              class="control"
+              onClick={() => {
+                if (!readonly) setOpened(true);
+              }}
+            >
+              <a class="button is-static">
+                <span class="icon">
+                  <i class="mdi mdi-calendar" />
+                </span>
+              </a>
+            </div>
+          </div>
+          {error && <p class="help is-danger">{error}</p>}
+        </div>
+
+        {!readonly && (
+          <span
+            data-tooltip={
+              withTimestampSupport
+                ? i18n.str`change value to unknown date`
+                : i18n.str`change value to empty`
+            }
+          >
+            <button
+              class="button is-info mr-3"
+              onClick={() => onChange(undefined as any)}
+            >
+              <i18n.Translate>clear</i18n.Translate>
+            </button>
+          </span>
+        )}
+        {withTimestampSupport && (
+          <span data-tooltip={i18n.str`change value to never`}>
+            <button
+              class="button is-info"
+              onClick={() => onChange({ t_s: "never" } as any)}
+            >
+              <i18n.Translate>never</i18n.Translate>
+            </button>
+          </span>
+        )}
+        {side}
+      </div>
+      <DatePicker
+        opened={opened}
+        closeFunction={() => setOpened(false)}
+        dateReceiver={(d) => {
+          if (withTimestampSupport) {
+            onChange({ t_s: d.getTime() / 1000 } as any);
+          } else {
+            onChange(d as any);
+          }
+        }}
+      />
+    </div>
+  );
+}
diff --git 
a/packages/auditor-backoffice-ui/src/components/form/InputDuration.tsx 
b/packages/auditor-backoffice-ui/src/components/form/InputDuration.tsx
new file mode 100644
index 000000000..7aa2703a4
--- /dev/null
+++ b/packages/auditor-backoffice-ui/src/components/form/InputDuration.tsx
@@ -0,0 +1,186 @@
+/*
+ This file is part of GNU Taler
+ (C) 2021-2023 Taler Systems S.A.
+
+ GNU Taler is free software; you can redistribute it and/or modify it under the
+ terms of the GNU General Public License as published by the Free Software
+ Foundation; either version 3, or (at your option) any later version.
+
+ GNU Taler is distributed in the hope that it will be useful, but WITHOUT ANY
+ WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
+ A PARTICULAR PURPOSE.  See the GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License along with
+ GNU Taler; see the file COPYING.  If not, see <http://www.gnu.org/licenses/>
+ */
+
+/**
+ *
+ * @author Sebastian Javier Marchano (sebasjm)
+ */
+import { useTranslationContext } from "@gnu-taler/web-util/browser";
+import { formatDuration, intervalToDuration } from "date-fns";
+import { ComponentChildren, h, VNode } from "preact";
+import { useState } from "preact/hooks";
+import { SimpleModal } from "../modal/index.js";
+import { DurationPicker } from "../picker/DurationPicker.js";
+import { InputProps, useField } from "./useField.js";
+import { Duration } from "@gnu-taler/taler-util";
+
+export interface Props<T> extends InputProps<T> {
+  expand?: boolean;
+  readonly?: boolean;
+  withForever?: boolean;
+  side?: ComponentChildren;
+  withoutClear?: boolean;
+}
+
+export function InputDuration<T>({
+  name,
+  expand,
+  placeholder,
+  tooltip,
+  label,
+  help,
+  readonly,
+  withForever,
+  withoutClear,
+  side,
+}: Props<keyof T>): VNode {
+  const [opened, setOpened] = useState(false);
+  const { i18n } = useTranslationContext();
+
+  const { error, required, value: anyValue, onChange } = useField<T>(name);
+  let strValue = "";
+  const value: Duration = anyValue
+  if (!value) {
+    strValue = "";
+  } else if (value.d_ms === "forever") {
+    strValue = i18n.str`forever`;
+  } else {
+    strValue = formatDuration(
+      intervalToDuration({ start: 0, end: value.d_ms }),
+      {
+        locale: {
+          formatDistance: (name, value) => {
+            switch (name) {
+              case "xMonths":
+                return i18n.str`${value}M`;
+              case "xYears":
+                return i18n.str`${value}Y`;
+              case "xDays":
+                return i18n.str`${value}d`;
+              case "xHours":
+                return i18n.str`${value}h`;
+              case "xMinutes":
+                return i18n.str`${value}min`;
+              case "xSeconds":
+                return i18n.str`${value}sec`;
+            }
+          },
+          localize: {
+            day: () => "s",
+            month: () => "m",
+            ordinalNumber: () => "th",
+            dayPeriod: () => "p",
+            quarter: () => "w",
+            era: () => "e",
+          },
+        },
+      },
+    );
+  }
+
+  return (
+    <div class="field is-horizontal">
+      <div class="field-label is-normal is-flex-grow-3">
+        <label class="label">
+          {label}
+          {tooltip && (
+            <span class="icon" data-tooltip={tooltip}>
+              <i class="mdi mdi-information" />
+            </span>
+          )}
+        </label>
+      </div>
+
+      <div class="is-flex-grow-3">
+        <div class="field-body ">
+          <div class="field">
+            <div class="field has-addons">
+              <p class={expand ? "control is-expanded " : "control "}>
+                <input
+                  class="input"
+                  type="text"
+                  readonly
+                  value={strValue}
+                  placeholder={placeholder}
+                  onClick={() => {
+                    if (!readonly) setOpened(true);
+                  }}
+                />
+                {required && (
+                  <span class="icon has-text-danger is-right">
+                    <i class="mdi mdi-alert" />
+                  </span>
+                )}
+              </p>
+              <div
+                class="control"
+                onClick={() => {
+                  if (!readonly) setOpened(true);
+                }}
+              >
+                <a class="button is-static">
+                  <span class="icon">
+                    <i class="mdi mdi-clock" />
+                  </span>
+                </a>
+              </div>
+            </div>
+            {error && <p class="help is-danger">{error}</p>}
+          </div>
+          {withForever && (
+            <span data-tooltip={i18n.str`change value to never`}>
+              <button
+                class="button is-info mr-3"
+                onClick={() => onChange({ d_ms: "forever" } as any)}
+              >
+                <i18n.Translate>forever</i18n.Translate>
+              </button>
+            </span>
+          )}
+          {!readonly && !withoutClear && (
+            <span data-tooltip={i18n.str`change value to empty`}>
+              <button
+                class="button is-info "
+                onClick={() => onChange(undefined as any)}
+              >
+                <i18n.Translate>clear</i18n.Translate>
+              </button>
+            </span>
+          )}
+          {side}
+        </div>
+        <span>
+          {help}
+        </span>
+      </div>
+
+
+      {opened && (
+        <SimpleModal onCancel={() => setOpened(false)}>
+          <DurationPicker
+            days
+            hours
+            minutes
+            value={!value || value.d_ms === "forever" ? 0 : value.d_ms}
+            onChange={(v) => {
+              onChange({ d_ms: v } as any);
+            }}
+          />
+        </SimpleModal>
+      )}
+    </div>
+  );
+}
diff --git a/packages/auditor-backoffice-ui/src/components/form/InputGroup.tsx 
b/packages/auditor-backoffice-ui/src/components/form/InputGroup.tsx
new file mode 100644
index 000000000..b5e0bd52b
--- /dev/null
+++ b/packages/auditor-backoffice-ui/src/components/form/InputGroup.tsx
@@ -0,0 +1,86 @@
+/*
+ This file is part of GNU Taler
+ (C) 2021-2023 Taler Systems S.A.
+
+ GNU Taler is free software; you can redistribute it and/or modify it under the
+ terms of the GNU General Public License as published by the Free Software
+ Foundation; either version 3, or (at your option) any later version.
+
+ GNU Taler is distributed in the hope that it will be useful, but WITHOUT ANY
+ WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
+ A PARTICULAR PURPOSE.  See the GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License along with
+ GNU Taler; see the file COPYING.  If not, see <http://www.gnu.org/licenses/>
+ */
+
+/**
+ *
+ * @author Sebastian Javier Marchano (sebasjm)
+ */
+import { ComponentChildren, h, VNode } from "preact";
+import { useState } from "preact/hooks";
+import { useGroupField } from "./useGroupField.js";
+
+export interface Props<T> {
+  name: T;
+  children: ComponentChildren;
+  label: ComponentChildren;
+  tooltip?: ComponentChildren;
+  alternative?: ComponentChildren;
+  fixed?: boolean;
+  initialActive?: boolean;
+}
+
+export function InputGroup<T>({
+  name,
+  label,
+  children,
+  tooltip,
+  alternative,
+  fixed,
+  initialActive,
+}: Props<keyof T>): VNode {
+  const [active, setActive] = useState(initialActive || fixed);
+  const group = useGroupField<T>(name);
+
+  return (
+    <div class="card">
+      <header class="card-header">
+        <p class="card-header-title">
+          {label}
+          {tooltip && (
+            <span class="icon has-tooltip-right" data-tooltip={tooltip}>
+              <i class="mdi mdi-information" />
+            </span>
+          )}
+          {group?.hasError && (
+            <span class="icon has-text-danger" data-tooltip={tooltip}>
+              <i class="mdi mdi-alert" />
+            </span>
+          )}
+        </p>
+        {!fixed && (
+          <button
+            class="card-header-icon"
+            aria-label="more options"
+            onClick={(): void => setActive(!active)}
+          >
+            <span class="icon">
+              {active ? (
+                <i class="mdi mdi-arrow-up" />
+              ) : (
+                <i class="mdi mdi-arrow-down" />
+              )}
+            </span>
+          </button>
+        )}
+      </header>
+      {active ? (
+        <div class="card-content">{children}</div>
+      ) : alternative ? (
+        <div class="card-content">{alternative}</div>
+      ) : undefined}
+    </div>
+  );
+}
diff --git a/packages/auditor-backoffice-ui/src/components/form/InputImage.tsx 
b/packages/auditor-backoffice-ui/src/components/form/InputImage.tsx
new file mode 100644
index 000000000..b024e2c6b
--- /dev/null
+++ b/packages/auditor-backoffice-ui/src/components/form/InputImage.tsx
@@ -0,0 +1,122 @@
+/*
+ This file is part of GNU Taler
+ (C) 2021-2023 Taler Systems S.A.
+
+ GNU Taler is free software; you can redistribute it and/or modify it under the
+ terms of the GNU General Public License as published by the Free Software
+ Foundation; either version 3, or (at your option) any later version.
+
+ GNU Taler is distributed in the hope that it will be useful, but WITHOUT ANY
+ WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
+ A PARTICULAR PURPOSE.  See the GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License along with
+ GNU Taler; see the file COPYING.  If not, see <http://www.gnu.org/licenses/>
+ */
+
+/**
+ *
+ * @author Sebastian Javier Marchano (sebasjm)
+ */
+import { useTranslationContext } from "@gnu-taler/web-util/browser";
+import { ComponentChildren, h, VNode } from "preact";
+import { useRef, useState } from "preact/hooks";
+import { MAX_IMAGE_SIZE as MAX_IMAGE_UPLOAD_SIZE } from 
"../../utils/constants.js";
+import { InputProps, useField } from "./useField.js";
+
+export interface Props<T> extends InputProps<T> {
+  expand?: boolean;
+  addonAfter?: ComponentChildren;
+  children?: ComponentChildren;
+}
+
+export function InputImage<T>({
+  name,
+  readonly,
+  placeholder,
+  tooltip,
+  label,
+  help,
+  children,
+  expand,
+}: Props<keyof T>): VNode {
+  const { error, value, onChange } = useField<T>(name);
+
+  const image = useRef<HTMLInputElement>(null);
+  const { i18n } = useTranslationContext();
+  const [sizeError, setSizeError] = useState(false);
+
+  return (
+    <div class="field is-horizontal">
+      <div class="field-label is-normal">
+        <label class="label">
+          {label}
+          {tooltip && (
+            <span class="icon has-tooltip-right" data-tooltip={tooltip}>
+              <i class="mdi mdi-information" />
+            </span>
+          )}
+        </label>
+      </div>
+      <div class="field-body is-flex-grow-3">
+        <div class="field">
+          <p class={expand ? "control is-expanded" : "control"}>
+            {value && (
+              <img
+                src={value}
+                style={{ width: 200, height: 200 }}
+                onClick={() => image.current?.click()}
+              />
+            )}
+            <input
+              ref={image}
+              style={{ display: "none" }}
+              type="file"
+              name={String(name)}
+              placeholder={placeholder}
+              readonly={readonly}
+              onChange={(e) => {
+                const f: FileList | null = e.currentTarget.files;
+                if (!f || f.length != 1) {
+                  return onChange(undefined!);
+                }
+                if (f[0].size > MAX_IMAGE_UPLOAD_SIZE) {
+                  setSizeError(true);
+                  return onChange(undefined!);
+                }
+                setSizeError(false);
+                return f[0].arrayBuffer().then((b) => {
+                  const b64 = window.btoa(
+                    new Uint8Array(b).reduce(
+                      (data, byte) => data + String.fromCharCode(byte),
+                      "",
+                    ),
+                  );
+                  return onChange(`data:${f[0].type};base64,${b64}` as any);
+                });
+              }}
+            />
+            {help}
+            {children}
+          </p>
+          {error && <p class="help is-danger">{error}</p>}
+          {sizeError && (
+            <p class="help is-danger">
+              <i18n.Translate>Image should be smaller than 1 
MB</i18n.Translate>
+            </p>
+          )}
+          {!value && (
+            <button class="button" onClick={() => image.current?.click()}>
+              <i18n.Translate>Add</i18n.Translate>
+            </button>
+          )}
+          {value && (
+            <button class="button" onClick={() => onChange(undefined!)}>
+              <i18n.Translate>Remove</i18n.Translate>
+            </button>
+          )}
+        </div>
+      </div>
+    </div>
+  );
+}
diff --git 
a/packages/auditor-backoffice-ui/src/components/form/InputLocation.tsx 
b/packages/auditor-backoffice-ui/src/components/form/InputLocation.tsx
new file mode 100644
index 000000000..a2fc8113e
--- /dev/null
+++ b/packages/auditor-backoffice-ui/src/components/form/InputLocation.tsx
@@ -0,0 +1,53 @@
+/*
+ This file is part of GNU Taler
+ (C) 2021-2023 Taler Systems S.A.
+
+ GNU Taler is free software; you can redistribute it and/or modify it under the
+ terms of the GNU General Public License as published by the Free Software
+ Foundation; either version 3, or (at your option) any later version.
+
+ GNU Taler is distributed in the hope that it will be useful, but WITHOUT ANY
+ WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
+ A PARTICULAR PURPOSE.  See the GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License along with
+ GNU Taler; see the file COPYING.  If not, see <http://www.gnu.org/licenses/>
+ */
+
+/**
+ *
+ * @author Sebastian Javier Marchano (sebasjm)
+ */
+import { Fragment, h } from "preact";
+import { useTranslationContext } from "@gnu-taler/web-util/browser";
+import { Input } from "./Input.js";
+
+export function InputLocation({ name }: { name: string }) {
+  const { i18n } = useTranslationContext();
+  return (
+    <>
+      <Input name={`${name}.country`} label={i18n.str`Country`} />
+      <Input
+        name={`${name}.address_lines`}
+        inputType="multiline"
+        label={i18n.str`Address`}
+        toStr={(v: string[] | undefined) => (!v ? "" : v.join("\n"))}
+        fromStr={(v: string) => v.split("\n")}
+      />
+      <Input
+        name={`${name}.building_number`}
+        label={i18n.str`Building number`}
+      />
+      <Input name={`${name}.building_name`} label={i18n.str`Building name`} />
+      <Input name={`${name}.street`} label={i18n.str`Street`} />
+      <Input name={`${name}.post_code`} label={i18n.str`Post code`} />
+      <Input name={`${name}.town_location`} label={i18n.str`Town location`} />
+      <Input name={`${name}.town`} label={i18n.str`Town`} />
+      <Input name={`${name}.district`} label={i18n.str`District`} />
+      <Input
+        name={`${name}.country_subdivision`}
+        label={i18n.str`Country subdivision`}
+      />
+    </>
+  );
+}
diff --git a/packages/auditor-backoffice-ui/src/components/form/InputNumber.tsx 
b/packages/auditor-backoffice-ui/src/components/form/InputNumber.tsx
new file mode 100644
index 000000000..3b5df1474
--- /dev/null
+++ b/packages/auditor-backoffice-ui/src/components/form/InputNumber.tsx
@@ -0,0 +1,60 @@
+/*
+ This file is part of GNU Taler
+ (C) 2021-2023 Taler Systems S.A.
+
+ GNU Taler is free software; you can redistribute it and/or modify it under the
+ terms of the GNU General Public License as published by the Free Software
+ Foundation; either version 3, or (at your option) any later version.
+
+ GNU Taler is distributed in the hope that it will be useful, but WITHOUT ANY
+ WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
+ A PARTICULAR PURPOSE.  See the GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License along with
+ GNU Taler; see the file COPYING.  If not, see <http://www.gnu.org/licenses/>
+ */
+
+/**
+ *
+ * @author Sebastian Javier Marchano (sebasjm)
+ */
+import { ComponentChildren, h } from "preact";
+import { InputWithAddon } from "./InputWithAddon.js";
+import { InputProps } from "./useField.js";
+
+export interface Props<T> extends InputProps<T> {
+  readonly?: boolean;
+  expand?: boolean;
+  side?: ComponentChildren;
+  children?: ComponentChildren;
+}
+
+export function InputNumber<T>({
+  name,
+  readonly,
+  placeholder,
+  tooltip,
+  label,
+  help,
+  expand,
+  children,
+  side,
+}: Props<keyof T>) {
+  return (
+    <InputWithAddon<T>
+      name={name}
+      readonly={readonly}
+      fromStr={(v) => (!v ? undefined : parseInt(v, 10))}
+      toStr={(v) => `${v}`}
+      inputType="number"
+      expand={expand}
+      label={label}
+      placeholder={placeholder}
+      help={help}
+      tooltip={tooltip}
+      inputExtra={{ min: 0 }}
+      children={children}
+      side={side}
+    />
+  );
+}
diff --git a/packages/auditor-backoffice-ui/src/components/form/InputPayto.tsx 
b/packages/auditor-backoffice-ui/src/components/form/InputPayto.tsx
new file mode 100644
index 000000000..6e88e8f2c
--- /dev/null
+++ b/packages/auditor-backoffice-ui/src/components/form/InputPayto.tsx
@@ -0,0 +1,52 @@
+/*
+ This file is part of GNU Taler
+ (C) 2021-2023 Taler Systems S.A.
+
+ GNU Taler is free software; you can redistribute it and/or modify it under the
+ terms of the GNU General Public License as published by the Free Software
+ Foundation; either version 3, or (at your option) any later version.
+
+ GNU Taler is distributed in the hope that it will be useful, but WITHOUT ANY
+ WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
+ A PARTICULAR PURPOSE.  See the GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License along with
+ GNU Taler; see the file COPYING.  If not, see <http://www.gnu.org/licenses/>
+ */
+
+/**
+ *
+ * @author Sebastian Javier Marchano (sebasjm)
+ */
+import { h, VNode } from "preact";
+import { InputArray } from "./InputArray.js";
+import { PAYTO_REGEX } from "../../utils/constants.js";
+import { InputProps } from "./useField.js";
+
+export type Props<T> = InputProps<T>;
+
+const PAYTO_START_REGEX = /^payto:\/\//;
+
+export function InputPayto<T>({
+  name,
+  readonly,
+  placeholder,
+  tooltip,
+  label,
+  help,
+}: Props<keyof T>): VNode {
+  return (
+    <InputArray<T>
+      name={name}
+      readonly={readonly}
+      addonBefore="payto://"
+      label={label}
+      placeholder={placeholder}
+      help={help}
+      tooltip={tooltip}
+      isValid={(v) => v && PAYTO_REGEX.test(v)}
+      toStr={(v?: string) => (!v ? "" : v.replace(PAYTO_START_REGEX, ""))}
+      fromStr={(v: string) => `payto://${v}`}
+    />
+  );
+}
diff --git 
a/packages/auditor-backoffice-ui/src/components/form/InputPaytoForm.stories.tsx 
b/packages/auditor-backoffice-ui/src/components/form/InputPaytoForm.stories.tsx
new file mode 100644
index 000000000..282e52278
--- /dev/null
+++ 
b/packages/auditor-backoffice-ui/src/components/form/InputPaytoForm.stories.tsx
@@ -0,0 +1,47 @@
+/*
+ This file is part of GNU Taler
+ (C) 2021-2023 Taler Systems S.A.
+
+ GNU Taler is free software; you can redistribute it and/or modify it under the
+ terms of the GNU General Public License as published by the Free Software
+ Foundation; either version 3, or (at your option) any later version.
+
+ GNU Taler is distributed in the hope that it will be useful, but WITHOUT ANY
+ WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
+ A PARTICULAR PURPOSE.  See the GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License along with
+ GNU Taler; see the file COPYING.  If not, see <http://www.gnu.org/licenses/>
+ */
+
+/**
+ *
+ * @author Sebastian Javier Marchano (sebasjm)
+ */
+
+import { h } from "preact";
+import * as tests from "@gnu-taler/web-util/testing";
+import { InputPaytoForm } from "./InputPaytoForm.js";
+import { FormProvider } from "./FormProvider.js";
+import { useState } from "preact/hooks";
+
+export default {
+  title: "Components/Form/PayTo",
+  component: InputPaytoForm,
+  argTypes: {
+    onUpdate: { action: "onUpdate" },
+    onBack: { action: "onBack" },
+  },
+};
+
+export const Example = tests.createExample(() => {
+  const initial = {
+    accounts: [],
+  };
+  const [form, updateForm] = useState<Partial<typeof initial>>(initial);
+  return (
+    <FormProvider valueHandler={updateForm} object={form}>
+      <InputPaytoForm name="accounts" label="Accounts:" />
+    </FormProvider>
+  );
+}, {});
diff --git 
a/packages/auditor-backoffice-ui/src/components/form/InputPaytoForm.tsx 
b/packages/auditor-backoffice-ui/src/components/form/InputPaytoForm.tsx
new file mode 100644
index 000000000..32545c89a
--- /dev/null
+++ b/packages/auditor-backoffice-ui/src/components/form/InputPaytoForm.tsx
@@ -0,0 +1,397 @@
+/*
+ This file is part of GNU Taler
+ (C) 2021-2023 Taler Systems S.A.
+
+ GNU Taler is free software; you can redistribute it and/or modify it under the
+ terms of the GNU General Public License as published by the Free Software
+ Foundation; either version 3, or (at your option) any later version.
+
+ GNU Taler is distributed in the hope that it will be useful, but WITHOUT ANY
+ WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
+ A PARTICULAR PURPOSE.  See the GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License along with
+ GNU Taler; see the file COPYING.  If not, see <http://www.gnu.org/licenses/>
+ */
+
+/**
+ *
+ * @author Sebastian Javier Marchano (sebasjm)
+ */
+import { parsePaytoUri, PaytoUriGeneric, stringifyPaytoUri } from 
"@gnu-taler/taler-util";
+import { useTranslationContext } from "@gnu-taler/web-util/browser";
+import { Fragment, h, VNode } from "preact";
+import { COUNTRY_TABLE } from "../../utils/constants.js";
+import { undefinedIfEmpty } from "../../utils/table.js";
+import { FormErrors, FormProvider } from "./FormProvider.js";
+import { Input } from "./Input.js";
+import { InputGroup } from "./InputGroup.js";
+import { InputSelector } from "./InputSelector.js";
+import { InputProps, useField } from "./useField.js";
+import { useEffect, useState } from "preact/hooks";
+
+export interface Props<T> extends InputProps<T> {
+  isValid?: (e: any) => boolean;
+}
+
+// type Entity = PaytoUriGeneric
+// https://datatracker.ietf.org/doc/html/rfc8905
+type Entity = {
+  // iban, bitcoin, x-taler-bank. it defined the format
+  target: string;
+  // path1 if the first field to be used
+  path1?: string;
+  // path2 if the second field to be used, optional
+  path2?: string;
+  // params of the payto uri
+  params: {
+    "receiver-name"?: string;
+    sender?: string;
+    message?: string;
+    amount?: string;
+    instruction?: string;
+    [name: string]: string | undefined;
+  };
+};
+
+function isEthereumAddress(address: string) {
+  if (!/^(0x)?[0-9a-f]{40}$/i.test(address)) {
+    return false;
+  } else if (
+    /^(0x|0X)?[0-9a-f]{40}$/.test(address) ||
+    /^(0x|0X)?[0-9A-F]{40}$/.test(address)
+  ) {
+    return true;
+  }
+  return checkAddressChecksum(address);
+}
+
+function checkAddressChecksum(address: string) {
+  //TODO implement ethereum checksum
+  return true;
+}
+
+function validateBitcoin(
+  addr: string,
+  i18n: ReturnType<typeof useTranslationContext>["i18n"],
+): string | undefined {
+  try {
+    const valid = /^(bc1|[13])[a-zA-HJ-NP-Z0-9]{25,39}$/.test(addr);
+    if (valid) return undefined;
+  } catch (e) {
+    console.log(e);
+  }
+  return i18n.str`This is not a valid bitcoin address.`;
+}
+
+function validateEthereum(
+  addr: string,
+  i18n: ReturnType<typeof useTranslationContext>["i18n"],
+): string | undefined {
+  try {
+    const valid = isEthereumAddress(addr);
+    if (valid) return undefined;
+  } catch (e) {
+    console.log(e);
+  }
+  return i18n.str`This is not a valid Ethereum address.`;
+}
+
+/**
+ * An IBAN is validated by converting it into an integer and performing a
+ * basic mod-97 operation (as described in ISO 7064) on it.
+ * If the IBAN is valid, the remainder equals 1.
+ *
+ * The algorithm of IBAN validation is as follows:
+ * 1.- Check that the total IBAN length is correct as per the country. If not, 
the IBAN is invalid
+ * 2.- Move the four initial characters to the end of the string
+ * 3.- Replace each letter in the string with two digits, thereby expanding 
the string, where A = 10, B = 11, ..., Z = 35
+ * 4.- Interpret the string as a decimal integer and compute the remainder of 
that number on division by 97
+ *
+ * If the remainder is 1, the check digit test is passed and the IBAN might be 
valid.
+ *
+ */
+function validateIBAN(
+  iban: string,
+  i18n: ReturnType<typeof useTranslationContext>["i18n"],
+): string | undefined {
+  // Check total length
+  if (iban.length < 4)
+    return i18n.str`IBAN numbers usually have more that 4 digits`;
+  if (iban.length > 34)
+    return i18n.str`IBAN numbers usually have less that 34 digits`;
+
+  const A_code = "A".charCodeAt(0);
+  const Z_code = "Z".charCodeAt(0);
+  const IBAN = iban.toUpperCase();
+  // check supported country
+  const code = IBAN.substr(0, 2);
+  const found = code in COUNTRY_TABLE;
+  if (!found) return i18n.str`IBAN country code not found`;
+
+  // 2.- Move the four initial characters to the end of the string
+  const step2 = IBAN.substr(4) + iban.substr(0, 4);
+  const step3 = Array.from(step2)
+    .map((letter) => {
+      const code = letter.charCodeAt(0);
+      if (code < A_code || code > Z_code) return letter;
+      return `${letter.charCodeAt(0) - "A".charCodeAt(0) + 10}`;
+    })
+    .join("");
+
+  function calculate_iban_checksum(str: string): number {
+    const numberStr = str.substr(0, 5);
+    const rest = str.substr(5);
+    const number = parseInt(numberStr, 10);
+    const result = number % 97;
+    if (rest.length > 0) {
+      return calculate_iban_checksum(`${result}${rest}`);
+    }
+    return result;
+  }
+
+  const checksum = calculate_iban_checksum(step3);
+  if (checksum !== 1)
+    return i18n.str`IBAN number is not valid, checksum is wrong`;
+  return undefined;
+}
+
+// const targets = ['ach', 'bic', 'iban', 'upi', 'bitcoin', 'ilp', 'void', 
'x-taler-bank']
+const targets = [
+  "Choose one...",
+  "iban",
+  "x-taler-bank",
+  "bitcoin",
+  "ethereum",
+];
+const noTargetValue = targets[0];
+const defaultTarget: Entity = {
+  target: noTargetValue,
+  params: {},
+};
+
+export function InputPaytoForm<T>({
+  name,
+  readonly,
+  label,
+  tooltip,
+}: Props<keyof T>): VNode {
+  const { value: initialValueStr, onChange } = useField<T>(name);
+
+  const initialPayto = parsePaytoUri(initialValueStr ?? "")
+  const paths = !initialPayto ? [] : initialPayto.targetPath.split("/")
+  const initialPath1 = paths.length >= 1 ? paths[0] : undefined;
+  const initialPath2 = paths.length >= 2 ? paths[1] : undefined;
+  const initial: Entity = initialPayto === undefined ? defaultTarget : {
+    target: initialPayto.targetType,
+    params: initialPayto.params,
+    path1: initialPath1,
+    path2: initialPath2,
+  }
+  const [value, setValue] = useState<Partial<Entity>>(initial)
+
+  const { i18n } = useTranslationContext();
+
+  const errors: FormErrors<Entity> = {
+    target:
+      value.target === noTargetValue
+        ? i18n.str`required`
+        : undefined,
+    path1: !value.path1
+      ? i18n.str`required`
+      : value.target === "iban"
+        ? validateIBAN(value.path1, i18n)
+        : value.target === "bitcoin"
+          ? validateBitcoin(value.path1, i18n)
+          : value.target === "ethereum"
+            ? validateEthereum(value.path1, i18n)
+            : undefined,
+    path2:
+      value.target === "x-taler-bank"
+        ? !value.path2
+          ? i18n.str`required`
+          : undefined
+        : undefined,
+    params: undefinedIfEmpty({
+      "receiver-name": !value.params?.["receiver-name"]
+        ? i18n.str`required`
+        : undefined,
+    }),
+  };
+
+  const hasErrors = Object.keys(errors).some(
+    (k) => (errors as any)[k] !== undefined,
+  );
+  const str = hasErrors || !value.target ? undefined : stringifyPaytoUri({
+    targetType: value.target,
+    targetPath: value.path2 ? `${value.path1}/${value.path2}` : (value.path1 
?? ""),
+    params: value.params ?? {} as any,
+    isKnown: false,
+  })
+  useEffect(() => {
+    onChange(str as any)
+  }, [str])
+
+  // const submit = useCallback((): void => {
+  //   // const accounts: MerchantBackend.BankAccounts.AccountAddDetails[] = 
paytos;
+  //   // const alreadyExists =
+  //   //   accounts.findIndex((x) => x.payto_uri === paytoURL) !== -1;
+  //   // if (!alreadyExists) {
+  //   const newValue: MerchantBackend.BankAccounts.AccountAddDetails = {
+  //     payto_uri: paytoURL,
+  //   };
+  //   if (value.auth) {
+  //     if (value.auth.url) {
+  //       newValue.credit_facade_url = value.auth.url;
+  //     }
+  //     if (value.auth.type === "none") {
+  //       newValue.credit_facade_credentials = {
+  //         type: "none",
+  //       };
+  //     }
+  //     if (value.auth.type === "basic") {
+  //       newValue.credit_facade_credentials = {
+  //         type: "basic",
+  //         username: value.auth.username ?? "",
+  //         password: value.auth.password ?? "",
+  //       };
+  //     }
+  //   }
+  //   onChange(newValue as any);
+  //   // }
+  //   // valueHandler(defaultTarget);
+  // }, [value]);
+
+  //FIXME: translating plural singular
+  return (
+    <InputGroup name="payto" label={label} fixed tooltip={tooltip}>
+      <FormProvider<Entity>
+        name="tax"
+        errors={errors}
+        object={value}
+        valueHandler={setValue}
+      >
+        <InputSelector<Entity>
+          name="target"
+          label={i18n.str`Account type`}
+          tooltip={i18n.str`Method to use for wire transfer`}
+          values={targets}
+          readonly={readonly}
+          toStr={(v) => (v === noTargetValue ? i18n.str`Choose one...` : v)}
+        />
+
+        {value.target === "ach" && (
+          <Fragment>
+            <Input<Entity>
+              name="path1"
+              label={i18n.str`Routing`}
+              readonly={readonly}
+              tooltip={i18n.str`Routing number.`}
+            />
+            <Input<Entity>
+              name="path2"
+              label={i18n.str`Account`}
+              readonly={readonly}
+              tooltip={i18n.str`Account number.`}
+            />
+          </Fragment>
+        )}
+        {value.target === "bic" && (
+          <Fragment>
+            <Input<Entity>
+              name="path1"
+              label={i18n.str`Code`}
+              readonly={readonly}
+              tooltip={i18n.str`Business Identifier Code.`}
+            />
+          </Fragment>
+        )}
+        {value.target === "iban" && (
+          <Fragment>
+            <Input<Entity>
+              name="path1"
+              label={i18n.str`IBAN`}
+              tooltip={i18n.str`International Bank Account Number.`}
+              readonly={readonly}
+              placeholder="DE1231231231"
+              inputExtra={{ style: { textTransform: "uppercase" } }}
+            />
+          </Fragment>
+        )}
+        {value.target === "upi" && (
+          <Fragment>
+            <Input<Entity>
+              name="path1"
+              readonly={readonly}
+              label={i18n.str`Account`}
+              tooltip={i18n.str`Unified Payment Interface.`}
+            />
+          </Fragment>
+        )}
+        {value.target === "bitcoin" && (
+          <Fragment>
+            <Input<Entity>
+              name="path1"
+              readonly={readonly}
+              label={i18n.str`Address`}
+              tooltip={i18n.str`Bitcoin protocol.`}
+            />
+          </Fragment>
+        )}
+        {value.target === "ethereum" && (
+          <Fragment>
+            <Input<Entity>
+              name="path1"
+              readonly={readonly}
+              label={i18n.str`Address`}
+              tooltip={i18n.str`Ethereum protocol.`}
+            />
+          </Fragment>
+        )}
+        {value.target === "ilp" && (
+          <Fragment>
+            <Input<Entity>
+              name="path1"
+              readonly={readonly}
+              label={i18n.str`Address`}
+              tooltip={i18n.str`Interledger protocol.`}
+            />
+          </Fragment>
+        )}
+        {value.target === "void" && <Fragment />}
+        {value.target === "x-taler-bank" && (
+          <Fragment>
+            <Input<Entity>
+              name="path1"
+              readonly={readonly}
+              label={i18n.str`Host`}
+              tooltip={i18n.str`Bank host.`}
+            />
+            <Input<Entity>
+              name="path2"
+              readonly={readonly}
+              label={i18n.str`Account`}
+              tooltip={i18n.str`Bank account.`}
+            />
+          </Fragment>
+        )}
+
+        {/**
+         * Show additional fields apart from the payto
+         */}
+        {value.target !== noTargetValue && (
+          <Fragment>
+            <Input
+              name="params.receiver-name"
+              readonly={readonly}
+              label={i18n.str`Owner's name`}
+              tooltip={i18n.str`Legal name of the person holding the account.`}
+            />
+          </Fragment>
+        )}
+
+      </FormProvider>
+    </InputGroup>
+  );
+}
+
diff --git 
a/packages/auditor-backoffice-ui/src/components/form/InputSearchOnList.tsx 
b/packages/auditor-backoffice-ui/src/components/form/InputSearchOnList.tsx
new file mode 100644
index 000000000..be5800d14
--- /dev/null
+++ b/packages/auditor-backoffice-ui/src/components/form/InputSearchOnList.tsx
@@ -0,0 +1,204 @@
+/*
+ This file is part of GNU Taler
+ (C) 2021-2023 Taler Systems S.A.
+
+ GNU Taler is free software; you can redistribute it and/or modify it under the
+ terms of the GNU General Public License as published by the Free Software
+ Foundation; either version 3, or (at your option) any later version.
+
+ GNU Taler is distributed in the hope that it will be useful, but WITHOUT ANY
+ WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
+ A PARTICULAR PURPOSE.  See the GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License along with
+ GNU Taler; see the file COPYING.  If not, see <http://www.gnu.org/licenses/>
+ */
+
+/**
+ *
+ * @author Sebastian Javier Marchano (sebasjm)
+ */
+import { useTranslationContext } from "@gnu-taler/web-util/browser";
+import { h, VNode } from "preact";
+import { useState } from "preact/hooks";
+import emptyImage from "../../assets/empty.png";
+import { FormErrors, FormProvider } from "./FormProvider.js";
+import { InputWithAddon } from "./InputWithAddon.js";
+import { TranslatedString } from "@gnu-taler/taler-util";
+
+type Entity = {
+  id: string,
+  description: string;
+  image?: string;
+  extra?: string;
+};
+
+export interface Props<T extends Entity> {
+  selected?: T;
+  onChange: (p?: T) => void;
+  label: TranslatedString;
+  list: T[];
+  withImage?: boolean;
+}
+
+interface Search {
+  name: string;
+}
+
+export function InputSearchOnList<T extends Entity>({
+  selected,
+  onChange,
+  label,
+  list,
+  withImage,
+}: Props<T>): VNode {
+  const [nameForm, setNameForm] = useState<Partial<Search>>({
+    name: "",
+  });
+
+  const errors: FormErrors<Search> = {
+    name: undefined,
+  };
+  const { i18n } = useTranslationContext();
+
+  if (selected) {
+    return (
+      <article class="media">
+        {withImage &&
+          <figure class="media-left">
+            <p class="image is-128x128">
+              <img src={selected.image ? selected.image : emptyImage} />
+            </p>
+          </figure>
+        }
+        <div class="media-content">
+          <div class="content">
+            <p class="media-meta">
+              <i18n.Translate>ID</i18n.Translate>: <b>{selected.id}</b>
+            </p>
+            <p>
+              <i18n.Translate>Description</i18n.Translate>:{" "}
+              {selected.description}
+            </p>
+            <div class="buttons is-right mt-5">
+              <button
+                class="button is-info"
+                onClick={() => onChange(undefined)}
+              >
+                clear
+              </button>
+            </div>
+          </div>
+        </div>
+      </article>
+    );
+  }
+
+  return (
+    <FormProvider<Search>
+      errors={errors}
+      object={nameForm}
+      valueHandler={setNameForm}
+    >
+      <InputWithAddon<Search>
+        name="name"
+        label={label}
+        tooltip={i18n.str`enter description or id`}
+        addonAfter={
+          <span class="icon">
+            <i class="mdi mdi-magnify" />
+          </span>
+        }
+      >
+        <div>
+          <DropdownList
+            name={nameForm.name}
+            list={list}
+            onSelect={(p) => {
+              setNameForm({ name: "" });
+              onChange(p);
+            }}
+            withImage={!!withImage}
+          />
+        </div>
+      </InputWithAddon>
+    </FormProvider>
+  );
+}
+
+interface DropdownListProps<T extends Entity> {
+  name?: string;
+  onSelect: (p: T) => void;
+  list: T[];
+  withImage: boolean;
+}
+
+function DropdownList<T extends Entity>({ name, onSelect, list, withImage }: 
DropdownListProps<T>) {
+  const { i18n } = useTranslationContext();
+  if (!name) {
+    /* FIXME
+      this BR is added to occupy the space that will be added when the 
+      dropdown appears
+    */
+    return (
+      <div>
+        <br />
+      </div>
+    );
+  }
+  const filtered = list.filter(
+    (p) => p.id.includes(name) || p.description.includes(name),
+  );
+
+  return (
+    <div class="dropdown is-active">
+      <div
+        class="dropdown-menu"
+        id="dropdown-menu"
+        role="menu"
+        style={{ minWidth: "20rem" }}
+      >
+        <div class="dropdown-content">
+          {!filtered.length ? (
+            <div class="dropdown-item">
+              <i18n.Translate>
+                no match found with that description or id
+              </i18n.Translate>
+            </div>
+          ) : (
+            filtered.map((p) => (
+              <div
+                key={p.id}
+                class="dropdown-item"
+                onClick={() => onSelect(p)}
+                style={{ cursor: "pointer" }}
+              >
+                <article class="media">
+                  {withImage &&
+                    <div class="media-left">
+                      <div class="image" style={{ minWidth: 64 }}>
+                        <img
+                          src={p.image ? p.image : emptyImage}
+                          style={{ width: 64, height: 64 }}
+                        />
+                      </div>
+                    </div>
+                  }
+                  <div class="media-content">
+                    <div class="content">
+                      <p>
+                        <strong>{p.id}</strong> {p.extra !== undefined ? 
<small>{p.extra}</small> : undefined}
+                        <br />
+                        {p.description}
+                      </p>
+                    </div>
+                  </div>
+                </article>
+              </div>
+            ))
+          )}
+        </div>
+      </div>
+    </div>
+  );
+}
diff --git 
a/packages/auditor-backoffice-ui/src/components/form/InputSecured.stories.tsx 
b/packages/auditor-backoffice-ui/src/components/form/InputSecured.stories.tsx
new file mode 100644
index 000000000..12ce6c6aa
--- /dev/null
+++ 
b/packages/auditor-backoffice-ui/src/components/form/InputSecured.stories.tsx
@@ -0,0 +1,61 @@
+/*
+ This file is part of GNU Taler
+ (C) 2021-2023 Taler Systems S.A.
+
+ GNU Taler is free software; you can redistribute it and/or modify it under the
+ terms of the GNU General Public License as published by the Free Software
+ Foundation; either version 3, or (at your option) any later version.
+
+ GNU Taler is distributed in the hope that it will be useful, but WITHOUT ANY
+ WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
+ A PARTICULAR PURPOSE.  See the GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License along with
+ GNU Taler; see the file COPYING.  If not, see <http://www.gnu.org/licenses/>
+ */
+
+/**
+ *
+ * @author Sebastian Javier Marchano (sebasjm)
+ */
+
+import { h, VNode } from "preact";
+import { useState } from "preact/hooks";
+import { FormProvider } from "./FormProvider.js";
+import { InputSecured } from "./InputSecured.js";
+
+export default {
+  title: "Components/Form/InputSecured",
+  component: InputSecured,
+};
+
+type T = { auth_token: string | null };
+
+export const InitialValueEmpty = (): VNode => {
+  const [state, setState] = useState<Partial<T>>({ auth_token: "" });
+  return (
+    <FormProvider<T> object={state} errors={{}} valueHandler={setState}>
+      Initial value: ''
+      <InputSecured<T> name="auth_token" label="Access token" />
+    </FormProvider>
+  );
+};
+
+export const InitialValueToken = (): VNode => {
+  const [state, setState] = useState<Partial<T>>({ auth_token: "token" });
+  return (
+    <FormProvider<T> object={state} errors={{}} valueHandler={setState}>
+      <InputSecured<T> name="auth_token" label="Access token" />
+    </FormProvider>
+  );
+};
+
+export const InitialValueNull = (): VNode => {
+  const [state, setState] = useState<Partial<T>>({ auth_token: null });
+  return (
+    <FormProvider<T> object={state} errors={{}} valueHandler={setState}>
+      Initial value: ''
+      <InputSecured<T> name="auth_token" label="Access token" />
+    </FormProvider>
+  );
+};
diff --git 
a/packages/auditor-backoffice-ui/src/components/form/InputSecured.tsx 
b/packages/auditor-backoffice-ui/src/components/form/InputSecured.tsx
new file mode 100644
index 000000000..9d1a3ab8e
--- /dev/null
+++ b/packages/auditor-backoffice-ui/src/components/form/InputSecured.tsx
@@ -0,0 +1,186 @@
+/*
+ This file is part of GNU Taler
+ (C) 2021-2023 Taler Systems S.A.
+
+ GNU Taler is free software; you can redistribute it and/or modify it under the
+ terms of the GNU General Public License as published by the Free Software
+ Foundation; either version 3, or (at your option) any later version.
+
+ GNU Taler is distributed in the hope that it will be useful, but WITHOUT ANY
+ WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
+ A PARTICULAR PURPOSE.  See the GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License along with
+ GNU Taler; see the file COPYING.  If not, see <http://www.gnu.org/licenses/>
+ */
+
+/**
+ *
+ * @author Sebastian Javier Marchano (sebasjm)
+ */
+import { useTranslationContext } from "@gnu-taler/web-util/browser";
+import { Fragment, h, VNode } from "preact";
+import { useState } from "preact/hooks";
+import { InputProps, useField } from "./useField.js";
+
+export type Props<T> = InputProps<T>;
+
+const TokenStatus = ({ prev, post }: any) => {
+  const { i18n } = useTranslationContext();
+  if (
+    (prev === undefined || prev === null) &&
+    (post === undefined || post === null)
+  )
+    return null;
+  return prev === post ? null : post === null ? (
+    <span class="tag is-danger is-align-self-center ml-2">
+      <i18n.Translate>Deleting</i18n.Translate>
+    </span>
+  ) : (
+    <span class="tag is-warning is-align-self-center ml-2">
+      <i18n.Translate>Changing</i18n.Translate>
+    </span>
+  );
+};
+
+export function InputSecured<T>({
+  name,
+  readonly,
+  placeholder,
+  tooltip,
+  label,
+  help,
+}: Props<keyof T>): VNode {
+  const { error, value, initial, onChange, toStr, fromStr } = 
useField<T>(name);
+
+  const [active, setActive] = useState(false);
+  const [newValue, setNuewValue] = useState("");
+
+  const { i18n } = useTranslationContext();
+
+  return (
+    <Fragment>
+      <div class="field is-horizontal">
+        <div class="field-label is-normal">
+          <label class="label">
+            {label}
+            {tooltip && (
+              <span class="icon has-tooltip-right" data-tooltip={tooltip}>
+                <i class="mdi mdi-information" />
+              </span>
+            )}
+          </label>
+        </div>
+        <div class="field-body is-flex-grow-3">
+          {!active ? (
+            <Fragment>
+              <div class="field has-addons">
+                <button
+                  class="button"
+                  onClick={(): void => {
+                    setActive(!active);
+                  }}
+                >
+                  <div class="icon is-left">
+                    <i class="mdi mdi-lock-reset" />
+                  </div>
+                  <span>
+                    <i18n.Translate>Manage access token</i18n.Translate>
+                  </span>
+                </button>
+                <TokenStatus prev={initial} post={value} />
+              </div>
+            </Fragment>
+          ) : (
+            <Fragment>
+              <div class="field has-addons">
+                <div class="control">
+                  <a class="button is-static">secret-token:</a>
+                </div>
+                <div class="control is-expanded">
+                  <input
+                    class="input"
+                    type="text"
+                    placeholder={placeholder}
+                    readonly={readonly || !active}
+                    disabled={readonly || !active}
+                    name={String(name)}
+                    value={newValue}
+                    onInput={(e): void => {
+                      setNuewValue(e.currentTarget.value);
+                    }}
+                  />
+                  {help}
+                </div>
+                <div class="control">
+                  <button
+                    class="button is-info"
+                    disabled={fromStr(newValue) === value}
+                    onClick={(): void => {
+                      onChange(fromStr(newValue));
+                      setActive(!active);
+                      setNuewValue("");
+                    }}
+                  >
+                    <div class="icon is-left">
+                      <i class="mdi mdi-lock-outline" />
+                    </div>
+                    <span>
+                      <i18n.Translate>Update</i18n.Translate>
+                    </span>
+                  </button>
+                </div>
+              </div>
+            </Fragment>
+          )}
+          {error ? <p class="help is-danger">{error}</p> : null}
+        </div>
+      </div>
+      {active && (
+        <div class="field is-horizontal">
+          <div class="field-body is-flex-grow-3">
+            <div class="level" style={{ width: "100%" }}>
+              <div class="level-right is-flex-grow-1">
+                <div class="level-item">
+                  <button
+                    class="button is-danger"
+                    disabled={null === value || undefined === value}
+                    onClick={(): void => {
+                      onChange(null!);
+                      setActive(!active);
+                      setNuewValue("");
+                    }}
+                  >
+                    <div class="icon is-left">
+                      <i class="mdi mdi-lock-open-variant" />
+                    </div>
+                    <span>
+                      <i18n.Translate>Remove</i18n.Translate>
+                    </span>
+                  </button>
+                </div>
+                <div class="level-item">
+                  <button
+                    class="button "
+                    onClick={(): void => {
+                      onChange(initial!);
+                      setActive(!active);
+                      setNuewValue("");
+                    }}
+                  >
+                    <div class="icon is-left">
+                      <i class="mdi mdi-lock-open-variant" />
+                    </div>
+                    <span>
+                      <i18n.Translate>Cancel</i18n.Translate>
+                    </span>
+                  </button>
+                </div>
+              </div>
+            </div>
+          </div>
+        </div>
+      )}
+    </Fragment>
+  );
+}
diff --git 
a/packages/auditor-backoffice-ui/src/components/form/InputSelector.tsx 
b/packages/auditor-backoffice-ui/src/components/form/InputSelector.tsx
new file mode 100644
index 000000000..a8dad5d89
--- /dev/null
+++ b/packages/auditor-backoffice-ui/src/components/form/InputSelector.tsx
@@ -0,0 +1,94 @@
+/*
+ This file is part of GNU Taler
+ (C) 2021-2023 Taler Systems S.A.
+
+ GNU Taler is free software; you can redistribute it and/or modify it under the
+ terms of the GNU General Public License as published by the Free Software
+ Foundation; either version 3, or (at your option) any later version.
+
+ GNU Taler is distributed in the hope that it will be useful, but WITHOUT ANY
+ WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
+ A PARTICULAR PURPOSE.  See the GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License along with
+ GNU Taler; see the file COPYING.  If not, see <http://www.gnu.org/licenses/>
+ */
+
+/**
+ *
+ * @author Sebastian Javier Marchano (sebasjm)
+ */
+import { h, VNode } from "preact";
+import { InputProps, useField } from "./useField.js";
+
+interface Props<T> extends InputProps<T> {
+  readonly?: boolean;
+  expand?: boolean;
+  values: any[];
+  toStr?: (v?: any) => string;
+  fromStr?: (s: string) => any;
+}
+
+const defaultToString = (f?: any): string => f || "";
+const defaultFromString = (v: string): any => v as any;
+
+export function InputSelector<T>({
+  name,
+  readonly,
+  expand,
+  placeholder,
+  tooltip,
+  label,
+  help,
+  values,
+  fromStr = defaultFromString,
+  toStr = defaultToString,
+}: Props<keyof T>): VNode {
+  const { error, value, onChange, required } = useField<T>(name);
+  return (
+    <div class="field is-horizontal">
+      <div class="field-label is-normal">
+        <label class="label">
+          {label}
+          {tooltip && (
+            <span class="icon has-tooltip-right" data-tooltip={tooltip}>
+              <i class="mdi mdi-information" />
+            </span>
+          )}
+        </label>
+      </div>
+      <div class="field-body is-flex-grow-3">
+        <div class="field has-icons-right">
+          <p class={expand ? "control is-expanded select" : "control select "}>
+            <select
+              class={error ? "select is-danger" : "select"}
+              name={String(name)}
+              disabled={readonly}
+              readonly={readonly}
+              onChange={(e) => {
+                onChange(fromStr(e.currentTarget.value));
+              }}
+            >
+              {placeholder && <option>{placeholder}</option>}
+              {values.map((v, i) => {
+                return (
+                  <option key={i} value={v} selected={value === v}>
+                    {toStr(v)}
+                  </option>
+                );
+              })}
+            </select>
+
+            {help}
+          </p>
+            {required && (
+              <span class="icon has-text-danger is-right" style={{height: 
"2.5em"}}>
+                <i class="mdi mdi-alert" />
+              </span>
+            )}
+          {error && <p class="help is-danger">{error}</p>}
+        </div>
+      </div>
+    </div>
+  );
+}
diff --git 
a/packages/auditor-backoffice-ui/src/components/form/InputStock.stories.tsx 
b/packages/auditor-backoffice-ui/src/components/form/InputStock.stories.tsx
new file mode 100644
index 000000000..668c65ea7
--- /dev/null
+++ b/packages/auditor-backoffice-ui/src/components/form/InputStock.stories.tsx
@@ -0,0 +1,162 @@
+/*
+ This file is part of GNU Taler
+ (C) 2021-2023 Taler Systems S.A.
+
+ GNU Taler is free software; you can redistribute it and/or modify it under the
+ terms of the GNU General Public License as published by the Free Software
+ Foundation; either version 3, or (at your option) any later version.
+
+ GNU Taler is distributed in the hope that it will be useful, but WITHOUT ANY
+ WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
+ A PARTICULAR PURPOSE.  See the GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License along with
+ GNU Taler; see the file COPYING.  If not, see <http://www.gnu.org/licenses/>
+ */
+
+/**
+ *
+ * @author Sebastian Javier Marchano (sebasjm)
+ */
+
+import { addDays } from "date-fns";
+import { h, VNode } from "preact";
+import { useState } from "preact/hooks";
+import { FormProvider } from "./FormProvider.js";
+import { InputStock, Stock } from "./InputStock.js";
+
+export default {
+  title: "Components/Form/InputStock",
+  component: InputStock,
+};
+
+type T = { stock?: Stock };
+
+export const CreateStockEmpty = () => {
+  const [state, setState] = useState<Partial<T>>({});
+  return (
+    <FormProvider<T>
+      name="product"
+      object={state}
+      errors={{}}
+      valueHandler={setState}
+    >
+      <InputStock<T> name="stock" label="Stock" />
+      <div>
+        <pre>{JSON.stringify(state, undefined, 2)}</pre>
+      </div>
+    </FormProvider>
+  );
+};
+
+export const CreateStockUnknownRestock = () => {
+  const [state, setState] = useState<Partial<T>>({
+    stock: {
+      current: 10,
+      lost: 0,
+      sold: 0,
+    },
+  });
+  return (
+    <FormProvider<T>
+      name="product"
+      object={state}
+      errors={{}}
+      valueHandler={setState}
+    >
+      <InputStock<T> name="stock" label="Stock" />
+      <div>
+        <pre>{JSON.stringify(state, undefined, 2)}</pre>
+      </div>
+    </FormProvider>
+  );
+};
+
+export const CreateStockNoRestock = () => {
+  const [state, setState] = useState<Partial<T>>({
+    stock: {
+      current: 10,
+      lost: 0,
+      sold: 0,
+      nextRestock: { t_s: "never" },
+    },
+  });
+  return (
+    <FormProvider<T>
+      name="product"
+      object={state}
+      errors={{}}
+      valueHandler={setState}
+    >
+      <InputStock<T> name="stock" label="Stock" />
+      <div>
+        <pre>{JSON.stringify(state, undefined, 2)}</pre>
+      </div>
+    </FormProvider>
+  );
+};
+
+export const CreateStockWithRestock = () => {
+  const [state, setState] = useState<Partial<T>>({
+    stock: {
+      current: 15,
+      lost: 0,
+      sold: 0,
+      nextRestock: { t_s: addDays(new Date(), 1).getTime() / 1000 },
+    },
+  });
+  return (
+    <FormProvider<T>
+      name="product"
+      object={state}
+      errors={{}}
+      valueHandler={setState}
+    >
+      <InputStock<T> name="stock" label="Stock" />
+      <div>
+        <pre>{JSON.stringify(state, undefined, 2)}</pre>
+      </div>
+    </FormProvider>
+  );
+};
+
+export const UpdatingProductWithManagedStock = () => {
+  const [state, setState] = useState<Partial<T>>({
+    stock: {
+      current: 100,
+      lost: 0,
+      sold: 0,
+      nextRestock: { t_s: addDays(new Date(), 1).getTime() / 1000 },
+    },
+  });
+  return (
+    <FormProvider<T>
+      name="product"
+      object={state}
+      errors={{}}
+      valueHandler={setState}
+    >
+      <InputStock<T> name="stock" label="Stock" alreadyExist />
+      <div>
+        <pre>{JSON.stringify(state, undefined, 2)}</pre>
+      </div>
+    </FormProvider>
+  );
+};
+
+export const UpdatingProductWithInfiniteStock = () => {
+  const [state, setState] = useState<Partial<T>>({});
+  return (
+    <FormProvider<T>
+      name="product"
+      object={state}
+      errors={{}}
+      valueHandler={setState}
+    >
+      <InputStock<T> name="stock" label="Stock" alreadyExist />
+      <div>
+        <pre>{JSON.stringify(state, undefined, 2)}</pre>
+      </div>
+    </FormProvider>
+  );
+};
diff --git a/packages/auditor-backoffice-ui/src/components/form/InputStock.tsx 
b/packages/auditor-backoffice-ui/src/components/form/InputStock.tsx
new file mode 100644
index 000000000..1d18685c5
--- /dev/null
+++ b/packages/auditor-backoffice-ui/src/components/form/InputStock.tsx
@@ -0,0 +1,224 @@
+/*
+ This file is part of GNU Taler
+ (C) 2021-2023 Taler Systems S.A.
+
+ GNU Taler is free software; you can redistribute it and/or modify it under the
+ terms of the GNU General Public License as published by the Free Software
+ Foundation; either version 3, or (at your option) any later version.
+
+ GNU Taler is distributed in the hope that it will be useful, but WITHOUT ANY
+ WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
+ A PARTICULAR PURPOSE.  See the GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License along with
+ GNU Taler; see the file COPYING.  If not, see <http://www.gnu.org/licenses/>
+ */
+
+/**
+ *
+ * @author Sebastian Javier Marchano (sebasjm)
+ */
+import { useTranslationContext } from "@gnu-taler/web-util/browser";
+import { Fragment, h } from "preact";
+import { useLayoutEffect, useState } from "preact/hooks";
+import { MerchantBackend, Timestamp } from "../../declaration.js";
+import { FormErrors, FormProvider } from "./FormProvider.js";
+import { InputDate } from "./InputDate.js";
+import { InputGroup } from "./InputGroup.js";
+import { InputLocation } from "./InputLocation.js";
+import { InputNumber } from "./InputNumber.js";
+import { InputProps, useField } from "./useField.js";
+
+export interface Props<T> extends InputProps<T> {
+  alreadyExist?: boolean;
+}
+
+type Entity = Stock;
+
+export interface Stock {
+  current: number;
+  lost: number;
+  sold: number;
+  address?: MerchantBackend.Location;
+  nextRestock?: Timestamp;
+}
+
+interface StockDelta {
+  incoming: number;
+  lost: number;
+}
+
+export function InputStock<T>({
+  name,
+  tooltip,
+  label,
+  alreadyExist,
+}: Props<keyof T>) {
+  const { error, value, onChange } = useField<T>(name);
+
+  const [errors, setErrors] = useState<FormErrors<Entity>>({});
+
+  const [formValue, valueHandler] = useState<Partial<Entity>>(value);
+  const [addedStock, setAddedStock] = useState<StockDelta>({
+    incoming: 0,
+    lost: 0,
+  });
+  const { i18n } = useTranslationContext();
+
+  useLayoutEffect(() => {
+    if (!formValue) {
+      onChange(undefined as any);
+    } else {
+      onChange({
+        ...formValue,
+        current: (formValue?.current || 0) + addedStock.incoming,
+        lost: (formValue?.lost || 0) + addedStock.lost,
+      } as any);
+    }
+  }, [formValue, addedStock]);
+
+  if (!formValue) {
+    return (
+      <Fragment>
+        <div class="field is-horizontal">
+          <div class="field-label is-normal">
+            <label class="label">
+              {label}
+              {tooltip && (
+                <span class="icon has-tooltip-right" data-tooltip={tooltip}>
+                  <i class="mdi mdi-information" />
+                </span>
+              )}
+            </label>
+          </div>
+          <div class="field-body is-flex-grow-3">
+            <div class="field has-addons">
+              {!alreadyExist ? (
+                <button
+                  class="button"
+                  data-tooltip={i18n.str`click here to configure the stock of 
the product, leave it as is and the backend will not control stock`}
+                  onClick={(): void => {
+                    valueHandler({
+                      current: 0,
+                      lost: 0,
+                      sold: 0,
+                    } as Stock as any);
+                  }}
+                >
+                  <span>
+                    <i18n.Translate>Manage stock</i18n.Translate>
+                  </span>
+                </button>
+              ) : (
+                <button
+                  class="button"
+                  data-tooltip={i18n.str`this product has been configured 
without stock control`}
+                  disabled
+                >
+                  <span>
+                    <i18n.Translate>Infinite</i18n.Translate>
+                  </span>
+                </button>
+              )}
+            </div>
+          </div>
+        </div>
+      </Fragment>
+    );
+  }
+
+  const currentStock =
+    (formValue.current || 0) - (formValue.lost || 0) - (formValue.sold || 0);
+
+  const stockAddedErrors: FormErrors<typeof addedStock> = {
+    lost:
+      currentStock + addedStock.incoming < addedStock.lost
+        ? i18n.str`lost cannot be greater than current and incoming (max ${
+            currentStock + addedStock.incoming
+          })`
+        : undefined,
+  };
+
+  // const stockUpdateDescription = stockAddedErrors.lost ? '' : (
+  //   !!addedStock.incoming || !!addedStock.lost ?
+  //     i18n.str`current stock will change from ${currentStock} to 
${currentStock + addedStock.incoming - addedStock.lost}` :
+  //     i18n.str`current stock will stay at ${currentStock}`
+  // )
+
+  return (
+    <Fragment>
+      <div class="card">
+        <header class="card-header">
+          <p class="card-header-title">
+            {label}
+            {tooltip && (
+              <span class="icon" data-tooltip={tooltip}>
+                <i class="mdi mdi-information" />
+              </span>
+            )}
+          </p>
+        </header>
+        <div class="card-content">
+          <FormProvider<Entity>
+            name="stock"
+            errors={errors}
+            object={formValue}
+            valueHandler={valueHandler}
+          >
+            {alreadyExist ? (
+              <Fragment>
+                <FormProvider
+                  name="added"
+                  errors={stockAddedErrors}
+                  object={addedStock}
+                  valueHandler={setAddedStock as any}
+                >
+                  <InputNumber name="incoming" label={i18n.str`Incoming`} />
+                  <InputNumber name="lost" label={i18n.str`Lost`} />
+                </FormProvider>
+
+                {/* <div class="field is-horizontal">
+              <div class="field-label is-normal" />
+              <div class="field-body is-flex-grow-3">
+                <div class="field">
+                  {stockUpdateDescription}
+                </div>
+              </div>
+            </div> */}
+              </Fragment>
+            ) : (
+              <InputNumber<Entity>
+                name="current"
+                label={i18n.str`Current`}
+                side={
+                  <button
+                    class="button is-danger"
+                    data-tooltip={i18n.str`remove stock control for this 
product`}
+                    onClick={(): void => {
+                      valueHandler(undefined as any);
+                    }}
+                  >
+                    <span>
+                      <i18n.Translate>without stock</i18n.Translate>
+                    </span>
+                  </button>
+                }
+              />
+            )}
+
+            <InputDate<Entity>
+              name="nextRestock"
+              label={i18n.str`Next restock`}
+              withTimestampSupport
+            />
+
+            <InputGroup<Entity> name="address" label={i18n.str`Warehouse 
address`}>
+              <InputLocation name="address" />
+            </InputGroup>
+          </FormProvider>
+        </div>
+      </div>
+    </Fragment>
+  );
+}
+// (
diff --git a/packages/auditor-backoffice-ui/src/components/form/InputTab.tsx 
b/packages/auditor-backoffice-ui/src/components/form/InputTab.tsx
new file mode 100644
index 000000000..2701768aa
--- /dev/null
+++ b/packages/auditor-backoffice-ui/src/components/form/InputTab.tsx
@@ -0,0 +1,90 @@
+/*
+ This file is part of GNU Taler
+ (C) 2021-2023 Taler Systems S.A.
+
+ GNU Taler is free software; you can redistribute it and/or modify it under the
+ terms of the GNU General Public License as published by the Free Software
+ Foundation; either version 3, or (at your option) any later version.
+
+ GNU Taler is distributed in the hope that it will be useful, but WITHOUT ANY
+ WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
+ A PARTICULAR PURPOSE.  See the GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License along with
+ GNU Taler; see the file COPYING.  If not, see <http://www.gnu.org/licenses/>
+ */
+
+/**
+ *
+ * @author Sebastian Javier Marchano (sebasjm)
+ */
+import { h, VNode } from "preact";
+import { InputProps, useField } from "./useField.js";
+
+interface Props<T> extends InputProps<T> {
+  readonly?: boolean;
+  expand?: boolean;
+  values: any[];
+  toStr?: (v?: any) => string;
+  fromStr?: (s: string) => any;
+}
+
+const defaultToString = (f?: any): string => f || "";
+const defaultFromString = (v: string): any => v as any;
+
+export function InputTab<T>({
+  name,
+  readonly,
+  expand,
+  placeholder,
+  tooltip,
+  label,
+  help,
+  values,
+  fromStr = defaultFromString,
+  toStr = defaultToString,
+}: Props<keyof T>): VNode {
+  const { error, value, onChange, required } = useField<T>(name);
+  return (
+    <div class="field is-horizontal">
+      <div class="field-label is-normal">
+        <label class="label">
+          {label}
+          {tooltip && (
+            <span class="icon has-tooltip-right" data-tooltip={tooltip}>
+              <i class="mdi mdi-information" />
+            </span>
+          )}
+        </label>
+      </div>
+      <div class="field-body is-flex-grow-3">
+        <div class="field has-icons-right">
+          <p class={expand ? "control is-expanded " : "control  "}>
+            <div class="tabs is-toggle is-fullwidth is-small">
+              <ul>
+                {values.map((v, i) => {
+                  return (
+                    <li key={i} class={value === v ? "is-active" : ""}
+                      onClick={(e) => { onChange(v) }}
+                    >
+                      <a style={{ cursor: "initial" }}>
+                        <span>{toStr(v)}</span>
+                      </a>
+                    </li>
+                  );
+                })}
+              </ul>
+            </div>
+            {help}
+          </p>
+          {required && (
+            <span class="icon has-text-danger is-right" style={{ height: 
"2.5em" }}>
+              <i class="mdi mdi-alert" />
+            </span>
+          )}
+          {error && <p class="help is-danger">{error}</p>}
+        </div>
+      </div>
+    </div>
+  );
+}
diff --git a/packages/auditor-backoffice-ui/src/components/form/InputTaxes.tsx 
b/packages/auditor-backoffice-ui/src/components/form/InputTaxes.tsx
new file mode 100644
index 000000000..b5722e4ec
--- /dev/null
+++ b/packages/auditor-backoffice-ui/src/components/form/InputTaxes.tsx
@@ -0,0 +1,147 @@
+/*
+ This file is part of GNU Taler
+ (C) 2021-2023 Taler Systems S.A.
+
+ GNU Taler is free software; you can redistribute it and/or modify it under the
+ terms of the GNU General Public License as published by the Free Software
+ Foundation; either version 3, or (at your option) any later version.
+
+ GNU Taler is distributed in the hope that it will be useful, but WITHOUT ANY
+ WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
+ A PARTICULAR PURPOSE.  See the GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License along with
+ GNU Taler; see the file COPYING.  If not, see <http://www.gnu.org/licenses/>
+ */
+
+/**
+ *
+ * @author Sebastian Javier Marchano (sebasjm)
+ */
+import { useTranslationContext } from "@gnu-taler/web-util/browser";
+import { h, VNode } from "preact";
+import { useCallback, useState } from "preact/hooks";
+import * as yup from "yup";
+import { MerchantBackend } from "../../declaration.js";
+import { TaxSchema as schema } from "../../schemas/index.js";
+import { FormErrors, FormProvider } from "./FormProvider.js";
+import { Input } from "./Input.js";
+import { InputGroup } from "./InputGroup.js";
+import { InputProps, useField } from "./useField.js";
+
+export interface Props<T> extends InputProps<T> {
+  isValid?: (e: any) => boolean;
+}
+
+type Entity = MerchantBackend.Tax;
+export function InputTaxes<T>({
+  name,
+  readonly,
+  label,
+}: Props<keyof T>): VNode {
+  const { value: taxes, onChange } = useField<T>(name);
+
+  const [value, valueHandler] = useState<Partial<Entity>>({});
+  // const [errors, setErrors] = useState<FormErrors<Entity>>({})
+
+  let errors: FormErrors<Entity> = {};
+
+  try {
+    schema.validateSync(value, { abortEarly: false });
+  } catch (err) {
+    if (err instanceof yup.ValidationError) {
+      const yupErrors = err.inner as yup.ValidationError[];
+      errors = yupErrors.reduce(
+        (prev, cur) =>
+          !cur.path ? prev : { ...prev, [cur.path]: cur.message },
+        {},
+      );
+    }
+  }
+  const hasErrors = Object.keys(errors).some(
+    (k) => (errors as any)[k] !== undefined,
+  );
+
+  const submit = useCallback((): void => {
+    onChange([value as any, ...taxes] as any);
+    valueHandler({});
+  }, [value]);
+
+  const { i18n } = useTranslationContext();
+
+  //FIXME: translating plural singular
+  return (
+    <InputGroup
+      name="tax"
+      label={label}
+      alternative={
+        taxes.length > 0 && (
+          <p>This product has {taxes.length} applicable taxes configured.</p>
+        )
+      }
+    >
+      <FormProvider<Entity>
+        name="tax"
+        errors={errors}
+        object={value}
+        valueHandler={valueHandler}
+      >
+        <div class="field is-horizontal">
+          <div class="field-label is-normal" />
+          <div class="field-body" style={{ display: "block" }}>
+            {taxes.map((v: any, i: number) => (
+              <div
+                key={i}
+                class="tags has-addons mt-3 mb-0 mr-3"
+                style={{ flexWrap: "nowrap" }}
+              >
+                <span
+                  class="tag is-medium is-info mb-0"
+                  style={{ maxWidth: "90%" }}
+                >
+                  <b>{v.tax}</b>: {v.name}
+                </span>
+                <a
+                  class="tag is-medium is-danger is-delete mb-0"
+                  onClick={() => {
+                    onChange(taxes.filter((f: any) => f !== v) as any);
+                    valueHandler(v);
+                  }}
+                />
+              </div>
+            ))}
+            {!taxes.length && i18n.str`No taxes configured for this product.`}
+          </div>
+        </div>
+
+        <Input<Entity>
+          name="tax"
+          label={i18n.str`Amount`}
+          tooltip={i18n.str`Taxes can be in currencies that differ from the 
main currency used by the merchant.`}
+        >
+          <i18n.Translate>
+            Enter currency and value separated with a colon, e.g.
+            &quot;USD:2.3&quot;.
+          </i18n.Translate>
+        </Input>
+
+        <Input<Entity>
+          name="name"
+          label={i18n.str`Description`}
+          tooltip={i18n.str`Legal name of the tax, e.g. VAT or import duties.`}
+        />
+
+        <div class="buttons is-right mt-5">
+          <button
+            class="button is-info"
+            data-tooltip={i18n.str`add tax to the tax list`}
+            disabled={hasErrors}
+            onClick={submit}
+          >
+            <i18n.Translate>Add</i18n.Translate>
+          </button>
+        </div>
+      </FormProvider>
+    </InputGroup>
+  );
+}
diff --git a/packages/auditor-backoffice-ui/src/components/form/InputToggle.tsx 
b/packages/auditor-backoffice-ui/src/components/form/InputToggle.tsx
new file mode 100644
index 000000000..f95dfcd05
--- /dev/null
+++ b/packages/auditor-backoffice-ui/src/components/form/InputToggle.tsx
@@ -0,0 +1,91 @@
+/*
+ This file is part of GNU Taler
+ (C) 2021-2023 Taler Systems S.A.
+
+ GNU Taler is free software; you can redistribute it and/or modify it under the
+ terms of the GNU General Public License as published by the Free Software
+ Foundation; either version 3, or (at your option) any later version.
+
+ GNU Taler is distributed in the hope that it will be useful, but WITHOUT ANY
+ WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
+ A PARTICULAR PURPOSE.  See the GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License along with
+ GNU Taler; see the file COPYING.  If not, see <http://www.gnu.org/licenses/>
+ */
+
+/**
+ *
+ * @author Sebastian Javier Marchano (sebasjm)
+ */
+import { h, VNode } from "preact";
+import { InputProps, useField } from "./useField.js";
+
+interface Props<T> extends InputProps<T> {
+  name: T;
+  readonly?: boolean;
+  expand?: boolean;
+  threeState?: boolean;
+  toBoolean?: (v?: any) => boolean | undefined;
+  fromBoolean?: (s: boolean | undefined) => any;
+}
+
+const defaultToBoolean = (f?: any): boolean | undefined => f || "";
+const defaultFromBoolean = (v: boolean | undefined): any => v as any;
+
+export function InputToggle<T>({
+  name,
+  readonly,
+  placeholder,
+  tooltip,
+  label,
+  help,
+  threeState,
+  expand,
+  fromBoolean = defaultFromBoolean,
+  toBoolean = defaultToBoolean,
+}: Props<keyof T>): VNode {
+  const { error, value, onChange } = useField<T>(name);
+
+  const onCheckboxClick = (): void => {
+    const c = toBoolean(value);
+    if (c === false && threeState) return onChange(undefined as any);
+    return onChange(fromBoolean(!c));
+  };
+
+  return (
+    <div class="field is-horizontal">
+      <div class="field-label is-normal">
+        <label class="label" >
+          {label}
+          {tooltip && (
+            <span class="icon has-tooltip-right" data-tooltip={tooltip}>
+              <i class="mdi mdi-information" />
+            </span>
+          )}
+        </label>
+      </div>
+      <div class="field-body is-flex-grow-3">
+        <div class="field">
+          <p class={expand ? "control is-expanded" : "control"}>
+            <label class="toggle" style={{ marginLeft: 4, marginTop: 0 }}>
+              <input
+                type="checkbox"
+                class={toBoolean(value) === undefined ? "is-indeterminate" : 
"toggle-checkbox"}
+                checked={toBoolean(value)}
+                placeholder={placeholder}
+                readonly={readonly}
+                name={String(name)}
+                disabled={readonly}
+                onChange={onCheckboxClick}
+              />
+              <div class="toggle-switch"></div>
+            </label>
+            {help}
+          </p>
+          {error && <p class="help is-danger">{error}</p>}
+        </div>
+      </div>
+    </div>
+  );
+}
diff --git 
a/packages/auditor-backoffice-ui/src/components/form/InputWithAddon.tsx 
b/packages/auditor-backoffice-ui/src/components/form/InputWithAddon.tsx
new file mode 100644
index 000000000..e9fd88770
--- /dev/null
+++ b/packages/auditor-backoffice-ui/src/components/form/InputWithAddon.tsx
@@ -0,0 +1,116 @@
+/*
+ This file is part of GNU Taler
+ (C) 2021-2023 Taler Systems S.A.
+
+ GNU Taler is free software; you can redistribute it and/or modify it under the
+ terms of the GNU General Public License as published by the Free Software
+ Foundation; either version 3, or (at your option) any later version.
+
+ GNU Taler is distributed in the hope that it will be useful, but WITHOUT ANY
+ WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
+ A PARTICULAR PURPOSE.  See the GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License along with
+ GNU Taler; see the file COPYING.  If not, see <http://www.gnu.org/licenses/>
+ */
+
+/**
+ *
+ * @author Sebastian Javier Marchano (sebasjm)
+ */
+import { ComponentChildren, h, VNode } from "preact";
+import { InputProps, useField } from "./useField.js";
+
+export interface Props<T> extends InputProps<T> {
+  expand?: boolean;
+  inputType?: "text" | "number" | "password";
+  addonBefore?: ComponentChildren;
+  addonAfter?: ComponentChildren;
+  addonAfterAction?: () => void;
+  toStr?: (v?: any) => string;
+  fromStr?: (s: string) => any;
+  inputExtra?: any;
+  children?: ComponentChildren;
+  side?: ComponentChildren;
+}
+
+const defaultToString = (f?: any): string => f || "";
+const defaultFromString = (v: string): any => v as any;
+
+export function InputWithAddon<T>({
+  name,
+  readonly,
+  addonBefore,
+  children,
+  expand,
+  label,
+  placeholder,
+  help,
+  tooltip,
+  inputType,
+  inputExtra,
+  side,
+  addonAfter,
+  addonAfterAction,
+  toStr = defaultToString,
+  fromStr = defaultFromString,
+}: Props<keyof T>): VNode {
+  const { error, value, onChange, required } = useField<T>(name);
+
+  return (
+    <div class="field is-horizontal">
+      <div class="field-label is-normal">
+        <label class="label">
+          {label}
+          {tooltip && (
+            <span class="icon has-tooltip-right" data-tooltip={tooltip}>
+              <i class="mdi mdi-information" />
+            </span>
+          )}
+        </label>
+      </div>
+      <div class="field-body is-flex-grow-3">
+        <div class="field">
+          <div class="field has-addons">
+            {addonBefore && (
+              <div class="control">
+                <a class="button is-static">{addonBefore}</a>
+              </div>
+            )}
+            <p
+              class={`control${expand ? " is-expanded" : ""}${required ? " 
has-icons-right" : ""
+                }`}
+            >
+              <input
+                {...(inputExtra || {})}
+                class={error ? "input is-danger" : "input"}
+                type={inputType}
+                placeholder={placeholder}
+                readonly={readonly}
+                disabled={readonly}
+                name={String(name)}
+                value={toStr(value)}
+                onChange={(e): void => 
onChange(fromStr(e.currentTarget.value))}
+              />
+              {required && (
+                <span class="icon has-text-danger is-right">
+                  <i class="mdi mdi-alert" />
+                </span>
+              )}
+              {children}
+            </p>
+            {addonAfter && (
+              <div class="control" onClick={addonAfterAction} style={{ cursor: 
addonAfterAction ? "pointer" : undefined }}>
+                <a class="button is-static">{addonAfter}</a>
+              </div>
+            )}
+          </div>
+          {error && <p class="help is-danger">{error}</p>}
+          <span class="has-text-grey">{help}</span>
+        </div>
+        {expand ? <div>{side}</div> : side}
+      </div>
+
+    </div>
+  );
+}
diff --git 
a/packages/auditor-backoffice-ui/src/components/form/JumpToElementById.tsx 
b/packages/auditor-backoffice-ui/src/components/form/JumpToElementById.tsx
new file mode 100644
index 000000000..2ff23dfd3
--- /dev/null
+++ b/packages/auditor-backoffice-ui/src/components/form/JumpToElementById.tsx
@@ -0,0 +1,59 @@
+import { TranslatedString } from "@gnu-taler/taler-util";
+import { useTranslationContext } from "@gnu-taler/web-util/browser";
+import { h, VNode } from "preact";
+import { useState } from "preact/hooks";
+
+export function JumpToElementById({ testIfExist, onSelect, palceholder, 
description }: { palceholder: TranslatedString, description: TranslatedString, 
testIfExist: (id: string) => Promise<any>, onSelect: (id: string) => void }): 
VNode {
+  const { i18n } = useTranslationContext()
+
+  const [error, setError] = useState<string | undefined>(
+    undefined,
+  );
+
+  const [id, setId] = useState<string>()
+  async function check(currentId: string | undefined): Promise<void> {
+    if (!currentId) {
+      setError(i18n.str`missing id`);
+      return;
+    }
+    try {
+      await testIfExist(currentId);
+      onSelect(currentId);
+      setError(undefined);
+    } catch {
+      setError(i18n.str`not found`);
+    }
+  }
+
+  return <div class="level">
+    <div class="level-left">
+      <div class="level-item">
+        <div class="field has-addons">
+          <div class="control">
+            <input
+              class={error ? "input is-danger" : "input"}
+              type="text"
+              value={id ?? ""}
+              onChange={(e) => setId(e.currentTarget.value)}
+              placeholder={palceholder}
+            />
+            {error && <p class="help is-danger">{error}</p>}
+          </div>
+          <span
+            class="has-tooltip-bottom"
+            data-tooltip={description}
+          >
+            <button
+              class="button"
+              onClick={(e) => check(id)}
+            >
+              <span class="icon">
+                <i class="mdi mdi-arrow-right" />
+              </span>
+            </button>
+          </span>
+        </div>
+      </div>
+    </div>
+  </div>
+}
diff --git a/packages/auditor-backoffice-ui/src/components/form/TextField.tsx 
b/packages/auditor-backoffice-ui/src/components/form/TextField.tsx
new file mode 100644
index 000000000..03f36dcbb
--- /dev/null
+++ b/packages/auditor-backoffice-ui/src/components/form/TextField.tsx
@@ -0,0 +1,71 @@
+/*
+ This file is part of GNU Taler
+ (C) 2021-2023 Taler Systems S.A.
+
+ GNU Taler is free software; you can redistribute it and/or modify it under the
+ terms of the GNU General Public License as published by the Free Software
+ Foundation; either version 3, or (at your option) any later version.
+
+ GNU Taler is distributed in the hope that it will be useful, but WITHOUT ANY
+ WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
+ A PARTICULAR PURPOSE.  See the GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License along with
+ GNU Taler; see the file COPYING.  If not, see <http://www.gnu.org/licenses/>
+ */
+
+/**
+ *
+ * @author Sebastian Javier Marchano (sebasjm)
+ */
+import { ComponentChildren, h, VNode } from "preact";
+import { useField, InputProps } from "./useField.js";
+
+interface Props<T> extends InputProps<T> {
+  inputType?: "text" | "number" | "multiline" | "password";
+  expand?: boolean;
+  side?: ComponentChildren;
+  children: ComponentChildren;
+}
+
+export function TextField<T>({
+  name,
+  tooltip,
+  label,
+  expand,
+  help,
+  children,
+  side,
+}: Props<keyof T>): VNode {
+  const { error } = useField<T>(name);
+  return (
+    <div class="field is-horizontal">
+      <div class="field-label is-normal">
+        <label class="label">
+          {label}
+          {tooltip && (
+            <span class="icon has-tooltip-right" data-tooltip={tooltip}>
+              <i class="mdi mdi-information" />
+            </span>
+          )}
+        </label>
+      </div>
+      <div class="field-body is-flex-grow-3">
+        <div class="field">
+          <p
+            class={
+              expand
+                ? "control is-expanded has-icons-right"
+                : "control has-icons-right"
+            }
+          >
+            {children}
+            {help}
+          </p>
+          {error && <p class="help is-danger">{error}</p>}
+        </div>
+        {side}
+      </div>
+    </div>
+  );
+}
diff --git a/packages/auditor-backoffice-ui/src/components/form/useField.tsx 
b/packages/auditor-backoffice-ui/src/components/form/useField.tsx
new file mode 100644
index 000000000..c7559faae
--- /dev/null
+++ b/packages/auditor-backoffice-ui/src/components/form/useField.tsx
@@ -0,0 +1,92 @@
+/*
+ This file is part of GNU Taler
+ (C) 2021-2023 Taler Systems S.A.
+
+ GNU Taler is free software; you can redistribute it and/or modify it under the
+ terms of the GNU General Public License as published by the Free Software
+ Foundation; either version 3, or (at your option) any later version.
+
+ GNU Taler is distributed in the hope that it will be useful, but WITHOUT ANY
+ WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
+ A PARTICULAR PURPOSE.  See the GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License along with
+ GNU Taler; see the file COPYING.  If not, see <http://www.gnu.org/licenses/>
+ */
+
+/**
+ *
+ * @author Sebastian Javier Marchano (sebasjm)
+ */
+
+import { ComponentChildren, VNode } from "preact";
+import { useState } from "preact/hooks";
+import { useFormContext } from "./FormProvider.js";
+
+interface Use<V> {
+  error?: string;
+  required: boolean;
+  value: any;
+  initial: any;
+  onChange: (v: V) => void;
+  toStr: (f: V | undefined) => string;
+  fromStr: (v: string) => V;
+}
+
+export function useField<T>(name: keyof T): Use<T[typeof name]> {
+  const { errors, object, initialObject, toStr, fromStr, valueHandler } =
+    useFormContext<T>();
+  type P = typeof name;
+  type V = T[P];
+  const [isDirty, setDirty] = useState(false);
+  const updateField =
+    (field: P) =>
+    (value: V): void => {
+      setDirty(true);
+      return valueHandler((prev) => {
+        return setValueDeeper(prev, String(field).split("."), value);
+      });
+    };
+
+  const defaultToString = (f?: V): string => String(!f ? "" : f);
+  const defaultFromString = (v: string): V => v as any;
+  const value = readField(object, String(name));
+  const initial = readField(initialObject, String(name));
+  const hasError = readField(errors, String(name));
+  return {
+    error: isDirty ? hasError : undefined,
+    required: !isDirty && hasError,
+    value,
+    initial,
+    onChange: updateField(name) as any,
+    toStr: toStr[name] ? toStr[name]! : defaultToString,
+    fromStr: fromStr[name] ? fromStr[name]! : defaultFromString,
+  };
+}
+/**
+ * read the field of an object an support accessing it using '.'
+ *
+ * @param object
+ * @param name
+ * @returns
+ */
+const readField = (object: any, name: string) => {
+  return name
+    .split(".")
+    .reduce((prev, current) => prev && prev[current], object);
+};
+
+const setValueDeeper = (object: any, names: string[], value: any): any => {
+  if (names.length === 0) return value;
+  const [head, ...rest] = names;
+  return { ...object, [head]: setValueDeeper(object[head] || {}, rest, value) 
};
+};
+
+export interface InputProps<T> {
+  name: T;
+  label: ComponentChildren;
+  placeholder?: string;
+  tooltip?: ComponentChildren;
+  readonly?: boolean;
+  help?: ComponentChildren;
+}
diff --git 
a/packages/auditor-backoffice-ui/src/components/form/useGroupField.tsx 
b/packages/auditor-backoffice-ui/src/components/form/useGroupField.tsx
new file mode 100644
index 000000000..9a445eb32
--- /dev/null
+++ b/packages/auditor-backoffice-ui/src/components/form/useGroupField.tsx
@@ -0,0 +1,41 @@
+/*
+ This file is part of GNU Taler
+ (C) 2021-2023 Taler Systems S.A.
+
+ GNU Taler is free software; you can redistribute it and/or modify it under the
+ terms of the GNU General Public License as published by the Free Software
+ Foundation; either version 3, or (at your option) any later version.
+
+ GNU Taler is distributed in the hope that it will be useful, but WITHOUT ANY
+ WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
+ A PARTICULAR PURPOSE.  See the GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License along with
+ GNU Taler; see the file COPYING.  If not, see <http://www.gnu.org/licenses/>
+ */
+
+/**
+ *
+ * @author Sebastian Javier Marchano (sebasjm)
+ */
+
+import { useFormContext } from "./FormProvider.js";
+
+interface Use {
+  hasError?: boolean;
+}
+
+export function useGroupField<T>(name: keyof T): Use {
+  const f = useFormContext<T>();
+  if (!f) return {};
+
+  return {
+    hasError: readField(f.errors, String(name)),
+  };
+}
+
+const readField = (object: any, name: string) => {
+  return name
+    .split(".")
+    .reduce((prev, current) => prev && prev[current], object);
+};
diff --git a/packages/auditor-backoffice-ui/src/components/index.stories.ts 
b/packages/auditor-backoffice-ui/src/components/index.stories.ts
new file mode 100644
index 000000000..c57ddab14
--- /dev/null
+++ b/packages/auditor-backoffice-ui/src/components/index.stories.ts
@@ -0,0 +1,17 @@
+/*
+ This file is part of GNU Taler
+ (C) 2021-2023 Taler Systems S.A.
+
+ GNU Taler is free software; you can redistribute it and/or modify it under the
+ terms of the GNU General Public License as published by the Free Software
+ Foundation; either version 3, or (at your option) any later version.
+
+ GNU Taler is distributed in the hope that it will be useful, but WITHOUT ANY
+ WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
+ A PARTICULAR PURPOSE.  See the GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License along with
+ GNU Taler; see the file COPYING.  If not, see <http://www.gnu.org/licenses/>
+ */
+
+export * as payto from "./form/InputPaytoForm.stories.js";
diff --git 
a/packages/auditor-backoffice-ui/src/components/instance/DefaultInstanceFormFields.tsx
 
b/packages/auditor-backoffice-ui/src/components/instance/DefaultInstanceFormFields.tsx
new file mode 100644
index 000000000..6f5881fc0
--- /dev/null
+++ 
b/packages/auditor-backoffice-ui/src/components/instance/DefaultInstanceFormFields.tsx
@@ -0,0 +1,124 @@
+/*
+ This file is part of GNU Taler
+ (C) 2021-2023 Taler Systems S.A.
+
+ GNU Taler is free software; you can redistribute it and/or modify it under the
+ terms of the GNU General Public License as published by the Free Software
+ Foundation; either version 3, or (at your option) any later version.
+
+ GNU Taler is distributed in the hope that it will be useful, but WITHOUT ANY
+ WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
+ A PARTICULAR PURPOSE.  See the GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License along with
+ GNU Taler; see the file COPYING.  If not, see <http://www.gnu.org/licenses/>
+ */
+
+/**
+ *
+ * @author Sebastian Javier Marchano (sebasjm)
+ */
+
+import { useTranslationContext } from "@gnu-taler/web-util/browser";
+import { Fragment, h, VNode } from "preact";
+import { useBackendContext } from "../../context/backend.js";
+import { Entity } from "../../paths/admin/create/CreatePage.js";
+import { Input } from "../form/Input.js";
+import { InputDuration } from "../form/InputDuration.js";
+import { InputGroup } from "../form/InputGroup.js";
+import { InputImage } from "../form/InputImage.js";
+import { InputLocation } from "../form/InputLocation.js";
+import { InputSelector } from "../form/InputSelector.js";
+import { InputToggle } from "../form/InputToggle.js";
+import { InputWithAddon } from "../form/InputWithAddon.js";
+
+export function DefaultInstanceFormFields({
+  readonlyId,
+  showId,
+}: {
+  readonlyId?: boolean;
+  showId: boolean;
+}): VNode {
+  const { i18n } = useTranslationContext();
+  const { url: backendURL } = useBackendContext()
+  return (
+    <Fragment>
+      {showId && (
+        <InputWithAddon<Entity>
+          name="id"
+          addonBefore={`${backendURL}/instances/`}
+          readonly={readonlyId}
+          label={i18n.str`Identifier`}
+          tooltip={i18n.str`Name of the instance in URLs. The 'default' 
instance is special in that it is used to administer other instances.`}
+        />
+      )}
+
+      <Input<Entity>
+        name="name"
+        label={i18n.str`Business name`}
+        tooltip={i18n.str`Legal name of the business represented by this 
instance.`}
+      />
+
+      <InputSelector<Entity>
+        name="user_type"
+        label={i18n.str`Type`}
+        tooltip={i18n.str`Different type of account can have different rules 
and requirements.`}
+        values={["business", "individual"]}
+      />
+
+      <Input<Entity>
+        name="email"
+        label={i18n.str`Email`}
+        tooltip={i18n.str`Contact email`}
+      />
+
+      <Input<Entity>
+        name="website"
+        label={i18n.str`Website URL`}
+        tooltip={i18n.str`URL.`}
+      />
+
+      <InputImage<Entity>
+        name="logo"
+        label={i18n.str`Logo`}
+        tooltip={i18n.str`Logo image.`}
+      />
+
+      <InputToggle<Entity>
+        name="use_stefan"
+        label={i18n.str`Pay transaction fee`}
+        tooltip={i18n.str`Assume the cost of the transaction of let the user 
pay for it.`}
+      />
+
+      <InputGroup
+        name="address"
+        label={i18n.str`Address`}
+        tooltip={i18n.str`Physical location of the merchant.`}
+      >
+        <InputLocation name="address" />
+      </InputGroup>
+
+      <InputGroup
+        name="jurisdiction"
+        label={i18n.str`Jurisdiction`}
+        tooltip={i18n.str`Jurisdiction for legal disputes with the merchant.`}
+      >
+        <InputLocation name="jurisdiction" />
+      </InputGroup>
+
+      <InputDuration<Entity>
+        name="default_pay_delay"
+        label={i18n.str`Default payment delay`}
+        withForever
+        tooltip={i18n.str`Time customers have to pay an order before the offer 
expires by default.`}
+      />
+
+      <InputDuration<Entity>
+        name="default_wire_transfer_delay"
+        label={i18n.str`Default wire transfer delay`}
+        tooltip={i18n.str`Maximum time an exchange is allowed to delay wiring 
funds to the merchant, enabling it to aggregate smaller payments into larger 
wire transfers and reducing wire fees.`}
+        withForever
+      />
+    </Fragment>
+  );
+}
diff --git 
a/packages/auditor-backoffice-ui/src/components/menu/LangSelector.tsx 
b/packages/auditor-backoffice-ui/src/components/menu/LangSelector.tsx
new file mode 100644
index 000000000..41fe1374a
--- /dev/null
+++ b/packages/auditor-backoffice-ui/src/components/menu/LangSelector.tsx
@@ -0,0 +1,92 @@
+/*
+ This file is part of GNU Taler
+ (C) 2021-2023 Taler Systems S.A.
+
+ GNU Taler is free software; you can redistribute it and/or modify it under the
+ terms of the GNU General Public License as published by the Free Software
+ Foundation; either version 3, or (at your option) any later version.
+
+ GNU Taler is distributed in the hope that it will be useful, but WITHOUT ANY
+ WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
+ A PARTICULAR PURPOSE.  See the GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License along with
+ GNU Taler; see the file COPYING.  If not, see <http://www.gnu.org/licenses/>
+ */
+
+/**
+ *
+ * @author Sebastian Javier Marchano (sebasjm)
+ */
+
+import { useTranslationContext } from "@gnu-taler/web-util/browser";
+import { h, VNode } from "preact";
+import { useState } from "preact/hooks";
+import langIcon from "../../assets/icons/languageicon.svg";
+import { strings as messages } from "../../i18n/strings.js";
+
+type LangsNames = {
+  [P in keyof typeof messages]: string;
+};
+
+const names: LangsNames = {
+  es: "Español [es]",
+  en: "English [en]",
+  fr: "Français [fr]",
+  de: "Deutsch [de]",
+  sv: "Svenska [sv]",
+  it: "Italiano [it]",
+};
+
+function getLangName(s: keyof LangsNames | string) {
+  if (names[s]) return names[s];
+  return s;
+}
+
+export function LangSelector(): VNode {
+  const [updatingLang, setUpdatingLang] = useState(false);
+  const { lang, changeLanguage } = useTranslationContext();
+
+  return (
+    <div class="dropdown is-active ">
+      <div class="dropdown-trigger">
+        <button
+          class="button has-tooltip-left"
+          data-tooltip="change language selection"
+          aria-haspopup="true"
+          aria-controls="dropdown-menu"
+          onClick={() => setUpdatingLang(!updatingLang)}
+        >
+          <div class="icon is-small is-left">
+            <img src={langIcon} />
+          </div>
+          <span>{getLangName(lang)}</span>
+          <div class="icon is-right">
+            <i class="mdi mdi-chevron-down" />
+          </div>
+        </button>
+      </div>
+      {updatingLang && (
+        <div class="dropdown-menu" id="dropdown-menu" role="menu">
+          <div class="dropdown-content">
+            {Object.keys(messages)
+              .filter((l) => l !== lang)
+              .map((l) => (
+                <a
+                  key={l}
+                  class="dropdown-item"
+                  value={l}
+                  onClick={() => {
+                    changeLanguage(l);
+                    setUpdatingLang(false);
+                  }}
+                >
+                  {getLangName(l)}
+                </a>
+              ))}
+          </div>
+        </div>
+      )}
+    </div>
+  );
+}
diff --git 
a/packages/auditor-backoffice-ui/src/components/menu/NavigationBar.tsx 
b/packages/auditor-backoffice-ui/src/components/menu/NavigationBar.tsx
new file mode 100644
index 000000000..9f1b33893
--- /dev/null
+++ b/packages/auditor-backoffice-ui/src/components/menu/NavigationBar.tsx
@@ -0,0 +1,72 @@
+/*
+ This file is part of GNU Taler
+ (C) 2021-2023 Taler Systems S.A.
+
+ GNU Taler is free software; you can redistribute it and/or modify it under the
+ terms of the GNU General Public License as published by the Free Software
+ Foundation; either version 3, or (at your option) any later version.
+
+ GNU Taler is distributed in the hope that it will be useful, but WITHOUT ANY
+ WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
+ A PARTICULAR PURPOSE.  See the GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License along with
+ GNU Taler; see the file COPYING.  If not, see <http://www.gnu.org/licenses/>
+ */
+
+/**
+ *
+ * @author Sebastian Javier Marchano (sebasjm)
+ */
+
+import { h, VNode } from "preact";
+import logo from "../../assets/logo-2021.svg";
+
+interface Props {
+  onMobileMenu: () => void;
+  title: string;
+}
+
+export function NavigationBar({ onMobileMenu, title }: Props): VNode {
+  return (
+    <nav
+      class="navbar is-fixed-top"
+      role="navigation"
+      aria-label="main navigation"
+    >
+      <div class="navbar-brand">
+        <span class="navbar-item" style={{ fontSize: 24, fontWeight: 900 }}>
+          {title}
+        </span>
+
+        <a
+          role="button"
+          class="navbar-burger"
+          aria-label="menu"
+          aria-expanded="false"
+          onClick={(e) => {
+            onMobileMenu();
+            e.stopPropagation();
+          }}
+        >
+          <span aria-hidden="true" />
+          <span aria-hidden="true" />
+          <span aria-hidden="true" />
+        </a>
+      </div>
+
+      <div class="navbar-menu ">
+        <a
+          class="navbar-start is-justify-content-center is-flex-grow-1"
+          href="https://taler.net";
+        >
+          <img src={logo} style={{ height: 35, margin: 10 }} />
+        </a>
+        <div class="navbar-end">
+          <div class="navbar-item" style={{ paddingTop: 4, paddingBottom: 4 }}>
+          </div>
+        </div>
+      </div>
+    </nav>
+  );
+}
diff --git a/packages/auditor-backoffice-ui/src/components/menu/SideBar.tsx 
b/packages/auditor-backoffice-ui/src/components/menu/SideBar.tsx
new file mode 100644
index 000000000..cfc00148e
--- /dev/null
+++ b/packages/auditor-backoffice-ui/src/components/menu/SideBar.tsx
@@ -0,0 +1,284 @@
+/*
+ This file is part of GNU Taler
+ (C) 2021-2023 Taler Systems S.A.
+
+ GNU Taler is free software; you can redistribute it and/or modify it under the
+ terms of the GNU General Public License as published by the Free Software
+ Foundation; either version 3, or (at your option) any later version.
+
+ GNU Taler is distributed in the hope that it will be useful, but WITHOUT ANY
+ WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
+ A PARTICULAR PURPOSE.  See the GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License along with
+ GNU Taler; see the file COPYING.  If not, see <http://www.gnu.org/licenses/>
+ */
+
+/**
+ *
+ * @author Sebastian Javier Marchano (sebasjm)
+ */
+
+import { useTranslationContext } from "@gnu-taler/web-util/browser";
+import { Fragment, h, VNode } from "preact";
+import { useBackendContext } from "../../context/backend.js";
+import { useConfigContext } from "../../context/config.js";
+import { useInstanceKYCDetails } from "../../hooks/instance.js";
+import { LangSelector } from "./LangSelector.js";
+
+const GIT_HASH = typeof __GIT_HASH__ !== "undefined" ? __GIT_HASH__ : 
undefined;
+const VERSION = typeof __VERSION__ !== "undefined" ? __VERSION__ : undefined;
+
+interface Props {
+  onLogout: () => void;
+  onShowSettings: () => void;
+  mobile?: boolean;
+  instance: string;
+  admin?: boolean;
+  mimic?: boolean;
+  isPasswordOk: boolean;
+}
+
+export function Sidebar({
+  mobile,
+  instance,
+  onShowSettings,
+  onLogout,
+  admin,
+  mimic,
+  isPasswordOk
+}: Props): VNode {
+  const config = useConfigContext();
+  const { url: backendURL } = useBackendContext()
+  const { i18n } = useTranslationContext();
+  const kycStatus = useInstanceKYCDetails();
+  const needKYC = kycStatus.ok && kycStatus.data.type === "redirect";
+
+  return (
+    <aside class="aside is-placed-left is-expanded" style={{ overflowY: 
"scroll" }}>
+      {mobile && (
+        <div
+          class="footer"
+          onClick={(e) => {
+            return e.stopImmediatePropagation();
+          }}
+        >
+          <LangSelector />
+        </div>
+      )}
+      <div class="aside-tools">
+        <div class="aside-tools-label">
+          <div>
+            <b>Taler</b> Backoffice
+          </div>
+          <div
+            class="is-size-7 has-text-right"
+            style={{ lineHeight: 0, marginTop: -10 }}
+          >
+            {VERSION} ({config.version})
+          </div>
+        </div>
+      </div>
+      <div class="menu is-menu-main">
+        {instance ? (
+          <Fragment>
+            <ul class="menu-list">
+              <li>
+                <a href={"/orders"} class="has-icon">
+                  <span class="icon">
+                    <i class="mdi mdi-cash-register" />
+                  </span>
+                  <span class="menu-item-label">
+                    <i18n.Translate>Orders</i18n.Translate>
+                  </span>
+                </a>
+              </li>
+              <li>
+                <a href={"/inventory"} class="has-icon">
+                  <span class="icon">
+                    <i class="mdi mdi-shopping" />
+                  </span>
+                  <span class="menu-item-label">
+                    <i18n.Translate>Inventory</i18n.Translate>
+                  </span>
+                </a>
+              </li>
+              <li>
+                <a href={"/transfers"} class="has-icon">
+                  <span class="icon">
+                    <i class="mdi mdi-arrow-left-right" />
+                  </span>
+                  <span class="menu-item-label">
+                    <i18n.Translate>Transfers</i18n.Translate>
+                  </span>
+                </a>
+              </li>
+              <li>
+                <a href={"/templates"} class="has-icon">
+                  <span class="icon">
+                    <i class="mdi mdi-newspaper" />
+                  </span>
+                  <span class="menu-item-label">
+                    <i18n.Translate>Templates</i18n.Translate>
+                  </span>
+                </a>
+              </li>
+              {needKYC && (
+                <li>
+                  <a href={"/kyc"} class="has-icon">
+                    <span class="icon">
+                      <i class="mdi mdi-account-check" />
+                    </span>
+                    <span class="menu-item-label">KYC Status</span>
+                  </a>
+                </li>
+              )}
+            </ul>
+            <p class="menu-label">
+              <i18n.Translate>Configuration</i18n.Translate>
+            </p>
+            <ul class="menu-list">
+              <li>
+                <a href={"/bank"} class="has-icon">
+                  <span class="icon">
+                    <i class="mdi mdi-bank" />
+                  </span>
+                  <span class="menu-item-label">
+                    <i18n.Translate>Bank account</i18n.Translate>
+                  </span>
+                </a>
+              </li>
+              <li>
+                <a href={"/otp-devices"} class="has-icon">
+                  <span class="icon">
+                    <i class="mdi mdi-lock" />
+                  </span>
+                  <span class="menu-item-label">
+                    <i18n.Translate>OTP Devices</i18n.Translate>
+                  </span>
+                </a>
+              </li>
+              <li>
+                <a href={"/reserves"} class="has-icon">
+                  <span class="icon">
+                    <i class="mdi mdi-cash" />
+                  </span>
+                  <span class="menu-item-label">Reserves</span>
+                </a>
+              </li>
+              <li>
+                <a href={"/webhooks"} class="has-icon">
+                  <span class="icon">
+                    <i class="mdi mdi-newspaper" />
+                  </span>
+                  <span class="menu-item-label">
+                    <i18n.Translate>Webhooks</i18n.Translate>
+                  </span>
+                </a>
+              </li>
+              <li>
+                <a href={"/settings"} class="has-icon">
+                  <span class="icon">
+                    <i class="mdi mdi-square-edit-outline" />
+                  </span>
+                  <span class="menu-item-label">
+                    <i18n.Translate>Settings</i18n.Translate>
+                  </span>
+                </a>
+              </li>
+              <li>
+                <a href={"/token"} class="has-icon">
+                  <span class="icon">
+                    <i class="mdi mdi-security" />
+                  </span>
+                  <span class="menu-item-label">
+                    <i18n.Translate>Access token</i18n.Translate>
+                  </span>
+                </a>
+              </li>
+            </ul>
+          </Fragment>
+        ) : undefined}
+        <p class="menu-label">
+          <i18n.Translate>Connection</i18n.Translate>
+        </p>
+        <ul class="menu-list">
+          <li>
+            <a class="has-icon is-state-info is-hoverable"
+              onClick={(): void => onShowSettings()}
+            >
+              <span class="icon">
+                <i class="mdi mdi-newspaper" />
+              </span>
+              <span class="menu-item-label">
+                <i18n.Translate>Interface</i18n.Translate>
+              </span>
+            </a>
+          </li>
+          <li>
+            <div>
+              <span style={{ width: "3rem" }} class="icon">
+                <i class="mdi mdi-web" />
+              </span>
+              <span class="menu-item-label">
+                {new URL(backendURL).hostname}
+              </span>
+            </div>
+          </li>
+          <li>
+            <div>
+              <span style={{ width: "3rem" }} class="icon">
+                ID
+              </span>
+              <span class="menu-item-label">
+                {!instance ? "default" : instance}
+              </span>
+            </div>
+          </li>
+          {admin && !mimic && (
+            <Fragment>
+              <p class="menu-label">
+                <i18n.Translate>Instances</i18n.Translate>
+              </p>
+              <li>
+                <a href={"/instance/new"} class="has-icon">
+                  <span class="icon">
+                    <i class="mdi mdi-plus" />
+                  </span>
+                  <span class="menu-item-label">
+                    <i18n.Translate>New</i18n.Translate>
+                  </span>
+                </a>
+              </li>
+              <li>
+                <a href={"/instances"} class="has-icon">
+                  <span class="icon">
+                    <i class="mdi mdi-format-list-bulleted" />
+                  </span>
+                  <span class="menu-item-label">
+                    <i18n.Translate>List</i18n.Translate>
+                  </span>
+                </a>
+              </li>
+            </Fragment>
+          )}
+          {isPasswordOk ?
+            <li>
+              <a
+                class="has-icon is-state-info is-hoverable"
+                onClick={(): void => onLogout()}
+              >
+                <span class="icon">
+                  <i class="mdi mdi-logout default" />
+                </span>
+                <span class="menu-item-label">
+                  <i18n.Translate>Log out</i18n.Translate>
+                </span>
+              </a>
+            </li> : undefined
+          }
+        </ul>
+      </div>
+    </aside>
+  );
+}
diff --git a/packages/auditor-backoffice-ui/src/components/menu/index.tsx 
b/packages/auditor-backoffice-ui/src/components/menu/index.tsx
new file mode 100644
index 000000000..03ae3b005
--- /dev/null
+++ b/packages/auditor-backoffice-ui/src/components/menu/index.tsx
@@ -0,0 +1,269 @@
+/*
+ This file is part of GNU Taler
+ (C) 2021-2023 Taler Systems S.A.
+
+ GNU Taler is free software; you can redistribute it and/or modify it under the
+ terms of the GNU General Public License as published by the Free Software
+ Foundation; either version 3, or (at your option) any later version.
+
+ GNU Taler is distributed in the hope that it will be useful, but WITHOUT ANY
+ WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
+ A PARTICULAR PURPOSE.  See the GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License along with
+ GNU Taler; see the file COPYING.  If not, see <http://www.gnu.org/licenses/>
+ */
+
+import { ComponentChildren, Fragment, h, VNode } from "preact";
+import { useEffect, useState } from "preact/hooks";
+import { AdminPaths } from "../../AdminRoutes.js";
+import { InstancePaths } from "../../InstanceRoutes.js";
+import { Notification } from "../../utils/types.js";
+import { NavigationBar } from "./NavigationBar.js";
+import { Sidebar } from "./SideBar.js";
+
+function getInstanceTitle(path: string, id: string): string {
+  switch (path) {
+    case InstancePaths.settings:
+      return `${id}: Settings`;
+    case InstancePaths.order_list:
+      return `${id}: Orders`;
+    case InstancePaths.order_new:
+      return `${id}: New order`;
+    case InstancePaths.inventory_list:
+      return `${id}: Inventory`;
+    case InstancePaths.deposit_confirmation_list:
+      return `${id}: Deposit Confirmation`;
+    case InstancePaths.inventory_new:
+      return `${id}: New product`;
+    case InstancePaths.inventory_update:
+      return `${id}: Update product`;
+    case InstancePaths.reserves_new:
+      return `${id}: New reserve`;
+    case InstancePaths.reserves_list:
+      return `${id}: Reserves`;
+    case InstancePaths.transfers_list:
+      return `${id}: Transfers`;
+    case InstancePaths.transfers_new:
+      return `${id}: New transfer`;
+    case InstancePaths.webhooks_list:
+      return `${id}: Webhooks`;
+    case InstancePaths.webhooks_new:
+      return `${id}: New webhook`;
+    case InstancePaths.webhooks_update:
+      return `${id}: Update webhook`;
+    case InstancePaths.otp_devices_list:
+      return `${id}: otp devices`;
+    case InstancePaths.otp_devices_new:
+      return `${id}: New otp devices`;
+    case InstancePaths.otp_devices_update:
+      return `${id}: Update otp devices`;
+    case InstancePaths.templates_new:
+      return `${id}: New template`;
+    case InstancePaths.templates_update:
+      return `${id}: Update template`;
+    case InstancePaths.templates_list:
+      return `${id}: Templates`;
+    case InstancePaths.templates_use:
+      return `${id}: Use template`;
+    case InstancePaths.interface:
+      return `${id}: Interface`;
+    default:
+      return "";
+  }
+}
+
+function getAdminTitle(path: string, instance: string) {
+  if (path === AdminPaths.new_instance) return `New instance`;
+  if (path === AdminPaths.list_instances) return `Instances`;
+  return getInstanceTitle(path, instance);
+}
+
+interface MenuProps {
+  title?: string;
+  path: string;
+  instance: string;
+  admin?: boolean;
+  onLogout?: () => void;
+  onShowSettings: () => void;
+  setInstanceName: (s: string) => void;
+  isPasswordOk: boolean;
+}
+
+function WithTitle({
+  title,
+  children,
+}: {
+  title: string;
+  children: ComponentChildren;
+}): VNode {
+  useEffect(() => {
+    document.title = `Taler Backoffice: ${title}`;
+  }, [title]);
+  return <Fragment>{children}</Fragment>;
+}
+
+export function Menu({
+  onLogout,
+  onShowSettings,
+  title,
+  instance,
+  path,
+  admin,
+  setInstanceName,
+  isPasswordOk
+}: MenuProps): VNode {
+  const [mobileOpen, setMobileOpen] = useState(false);
+
+  const titleWithSubtitle = title
+    ? title
+    : !admin
+      ? getInstanceTitle(path, instance)
+      : getAdminTitle(path, instance);
+  const adminInstance = instance === "default";
+  const mimic = admin && !adminInstance;
+  return (
+    <WithTitle title={titleWithSubtitle}>
+      <div
+        class={mobileOpen ? "has-aside-mobile-expanded" : ""}
+        onClick={() => setMobileOpen(false)}
+      >
+        <NavigationBar
+          onMobileMenu={() => setMobileOpen(!mobileOpen)}
+          title={titleWithSubtitle}
+        />
+
+        {onLogout && (
+          <Sidebar
+            onShowSettings={onShowSettings}
+            onLogout={onLogout}
+            admin={admin}
+            mimic={mimic}
+            instance={instance}
+            mobile={mobileOpen}
+            isPasswordOk={isPasswordOk}
+          />
+        )}
+
+        {mimic && (
+          <nav class="level" style={{
+            zIndex: 100,
+            position: "fixed",
+            width: "50%",
+            marginLeft: "20%"
+          }}>
+            <div class="level-item has-text-centered has-background-warning">
+              <p class="is-size-5">
+                You are viewing the instance <b>&quot;{instance}&quot;</b>.{" 
"}
+                <a
+                  href="#/instances"
+                  onClick={(e) => {
+                    setInstanceName("default");
+                  }}
+                >
+                  go back
+                </a>
+              </p>
+            </div>
+          </nav>
+        )}
+      </div>
+    </WithTitle>
+  );
+}
+
+interface NotYetReadyAppMenuProps {
+  title: string;
+  onShowSettings: () => void;
+  onLogout?: () => void;
+  isPasswordOk: boolean;
+}
+
+interface NotifProps {
+  notification?: Notification;
+}
+export function NotificationCard({
+  notification: n,
+}: NotifProps): VNode | null {
+  if (!n) return null;
+  return (
+    <div class="notification">
+      <div class="columns is-vcentered">
+        <div class="column is-12">
+          <article
+            class={
+              n.type === "ERROR"
+                ? "message is-danger"
+                : n.type === "WARN"
+                  ? "message is-warning"
+                  : "message is-info"
+            }
+          >
+            <div class="message-header">
+              <p>{n.message}</p>
+            </div>
+            {n.description && (
+              <div class="message-body">
+                <div>{n.description}</div>
+                {n.details && <pre>{n.details}</pre>}
+              </div>
+            )}
+          </article>
+        </div>
+      </div>
+    </div>
+  );
+}
+
+interface NotConnectedAppMenuProps {
+  title: string;
+}
+export function NotConnectedAppMenu({
+  title,
+}: NotConnectedAppMenuProps): VNode {
+  const [mobileOpen, setMobileOpen] = useState(false);
+
+  useEffect(() => {
+    document.title = `Taler Backoffice: ${title}`;
+  }, [title]);
+
+  return (
+    <div
+      class={mobileOpen ? "has-aside-mobile-expanded" : ""}
+      onClick={() => setMobileOpen(false)}
+    >
+      <NavigationBar
+        onMobileMenu={() => setMobileOpen(!mobileOpen)}
+        title={title}
+      />
+    </div>
+  );
+}
+
+export function NotYetReadyAppMenu({
+  onLogout,
+  onShowSettings,
+  title,
+  isPasswordOk
+}: NotYetReadyAppMenuProps): VNode {
+  const [mobileOpen, setMobileOpen] = useState(false);
+
+  useEffect(() => {
+    document.title = `Taler Backoffice: ${title}`;
+  }, [title]);
+
+  return (
+    <div
+      class={mobileOpen ? "has-aside-mobile-expanded" : ""}
+      onClick={() => setMobileOpen(false)}
+    >
+      <NavigationBar
+        onMobileMenu={() => setMobileOpen(!mobileOpen)}
+        title={title}
+      />
+      {onLogout && (
+        <Sidebar onShowSettings={onShowSettings} onLogout={onLogout} 
instance="" mobile={mobileOpen} isPasswordOk={isPasswordOk} />
+      )}
+    </div>
+  );
+}
diff --git a/packages/auditor-backoffice-ui/src/components/modal/index.tsx 
b/packages/auditor-backoffice-ui/src/components/modal/index.tsx
new file mode 100644
index 000000000..8372c84cc
--- /dev/null
+++ b/packages/auditor-backoffice-ui/src/components/modal/index.tsx
@@ -0,0 +1,496 @@
+/*
+ This file is part of GNU Taler
+ (C) 2021-2023 Taler Systems S.A.
+
+ GNU Taler is free software; you can redistribute it and/or modify it under the
+ terms of the GNU General Public License as published by the Free Software
+ Foundation; either version 3, or (at your option) any later version.
+
+ GNU Taler is distributed in the hope that it will be useful, but WITHOUT ANY
+ WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
+ A PARTICULAR PURPOSE.  See the GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License along with
+ GNU Taler; see the file COPYING.  If not, see <http://www.gnu.org/licenses/>
+ */
+
+/**
+ *
+ * @author Sebastian Javier Marchano (sebasjm)
+ */
+
+import { useTranslationContext } from "@gnu-taler/web-util/browser";
+import { ComponentChildren, Fragment, h, VNode } from "preact";
+import { useState } from "preact/hooks";
+import { useInstanceContext } from "../../context/instance.js";
+import { DEFAULT_REQUEST_TIMEOUT } from "../../utils/constants.js";
+import { Spinner } from "../exception/loading.js";
+import { FormProvider } from "../form/FormProvider.js";
+import { Input } from "../form/Input.js";
+
+interface Props {
+  active?: boolean;
+  description?: string;
+  onCancel?: () => void;
+  onConfirm?: () => void;
+  label?: string;
+  children?: ComponentChildren;
+  danger?: boolean;
+  disabled?: boolean;
+}
+
+export function ConfirmModal({
+  active,
+  description,
+  onCancel,
+  onConfirm,
+  children,
+  danger,
+  disabled,
+  label = "Confirm",
+}: Props): VNode {
+  const { i18n } = useTranslationContext();
+  return (
+    <div class={active ? "modal is-active" : "modal"}>
+      <div class="modal-background " onClick={onCancel} />
+      <div class="modal-card" style={{ maxWidth: 700 }}>
+        <header class="modal-card-head">
+          {!description ? null : (
+            <p class="modal-card-title">
+              <b>{description}</b>
+            </p>
+          )}
+          <button class="delete " aria-label="close" onClick={onCancel} />
+        </header>
+        <section class="modal-card-body">{children}</section>
+        <footer class="modal-card-foot">
+          <div class="buttons is-right" style={{ width: "100%" }}>
+            {onConfirm ? (
+              <Fragment>
+                <button class="button " onClick={onCancel}>
+                  <i18n.Translate>Cancel</i18n.Translate>
+                </button>
+
+                <button
+                  class={danger ? "button is-danger " : "button is-info "}
+                  disabled={disabled}
+                  onClick={onConfirm}
+                >
+                  <i18n.Translate>{label}</i18n.Translate>
+                </button>
+              </Fragment>
+            ) : (
+              <button class="button " onClick={onCancel}>
+                <i18n.Translate>Close</i18n.Translate>
+              </button>
+            )}
+          </div>
+        </footer>
+      </div>
+      <button
+        class="modal-close is-large "
+        aria-label="close"
+        onClick={onCancel}
+      />
+    </div>
+  );
+}
+
+export function ContinueModal({
+  active,
+  description,
+  onCancel,
+  onConfirm,
+  children,
+  disabled,
+}: Props): VNode {
+  const { i18n } = useTranslationContext();
+  return (
+    <div class={active ? "modal is-active" : "modal"}>
+      <div class="modal-background " onClick={onCancel} />
+      <div class="modal-card">
+        <header class="modal-card-head has-background-success">
+          {!description ? null : <p class="modal-card-title">{description}</p>}
+          <button class="delete " aria-label="close" onClick={onCancel} />
+        </header>
+        <section class="modal-card-body">{children}</section>
+        <footer class="modal-card-foot">
+          <div class="buttons is-right" style={{ width: "100%" }}>
+            <button
+              class="button is-success "
+              disabled={disabled}
+              onClick={onConfirm}
+            >
+              <i18n.Translate>Continue</i18n.Translate>
+            </button>
+          </div>
+        </footer>
+      </div>
+      <button
+        class="modal-close is-large "
+        aria-label="close"
+        onClick={onCancel}
+      />
+    </div>
+  );
+}
+
+export function SimpleModal({ onCancel, children }: any): VNode {
+  return (
+    <div class="modal is-active">
+      <div class="modal-background " onClick={onCancel} />
+      <div class="modal-card">
+        <section class="modal-card-body is-main-section">{children}</section>
+      </div>
+      <button
+        class="modal-close is-large "
+        aria-label="close"
+        onClick={onCancel}
+      />
+    </div>
+  );
+}
+
+export function ClearConfirmModal({
+  description,
+  onCancel,
+  onClear,
+  onConfirm,
+  children,
+}: Props & { onClear?: () => void }): VNode {
+  const { i18n } = useTranslationContext();
+  return (
+    <div class="modal is-active">
+      <div class="modal-background " onClick={onCancel} />
+      <div class="modal-card">
+        <header class="modal-card-head">
+          {!description ? null : <p class="modal-card-title">{description}</p>}
+          <button class="delete " aria-label="close" onClick={onCancel} />
+        </header>
+        <section class="modal-card-body is-main-section">{children}</section>
+        <footer class="modal-card-foot">
+          {onClear && (
+            <button
+              class="button is-danger"
+              onClick={onClear}
+              disabled={onClear === undefined}
+            >
+              <i18n.Translate>Clear</i18n.Translate>
+            </button>
+          )}
+          <div class="buttons is-right" style={{ width: "100%" }}>
+            <button class="button " onClick={onCancel}>
+              <i18n.Translate>Cancel</i18n.Translate>
+            </button>
+            <button
+              class="button is-info"
+              onClick={onConfirm}
+              disabled={onConfirm === undefined}
+            >
+              <i18n.Translate>Confirm</i18n.Translate>
+            </button>
+          </div>
+        </footer>
+      </div>
+      <button
+        class="modal-close is-large "
+        aria-label="close"
+        onClick={onCancel}
+      />
+    </div>
+  );
+}
+
+interface DeleteModalProps {
+  element: { id: string; name: string };
+  onCancel: () => void;
+  onConfirm: (id: string) => void;
+}
+
+export function DeleteModal({
+  element,
+  onCancel,
+  onConfirm,
+}: DeleteModalProps): VNode {
+  return (
+    <ConfirmModal
+      label={`Delete instance`}
+      description={`Delete the instance "${element.name}"`}
+      danger
+      active
+      onCancel={onCancel}
+      onConfirm={() => onConfirm(element.id)}
+    >
+      <p>
+        If you delete the instance named <b>&quot;{element.name}&quot;</b> 
(ID:{" "}
+        <b>{element.id}</b>), the merchant will no longer be able to process
+        orders or refunds
+      </p>
+      <p>
+        This action deletes the instance private key, but preserves all
+        transaction data. You can still access that data after deleting the
+        instance.
+      </p>
+      <p class="warning">
+        Deleting an instance <b>cannot be undone</b>.
+      </p>
+    </ConfirmModal>
+  );
+}
+
+export function PurgeModal({
+  element,
+  onCancel,
+  onConfirm,
+}: DeleteModalProps): VNode {
+  return (
+    <ConfirmModal
+      label={`Purge the instance`}
+      description={`Purge the instance "${element.name}"`}
+      danger
+      active
+      onCancel={onCancel}
+      onConfirm={() => onConfirm(element.id)}
+    >
+      <p>
+        If you purge the instance named <b>&quot;{element.name}&quot;</b> 
(ID:{" "}
+        <b>{element.id}</b>), you will also delete all it&apos;s transaction
+        data.
+      </p>
+      <p>
+        The instance will disappear from your list, and you will no longer be
+        able to access it&apos;s data.
+      </p>
+      <p class="warning">
+        Purging an instance <b>cannot be undone</b>.
+      </p>
+    </ConfirmModal>
+  );
+}
+
+interface UpdateTokenModalProps {
+  oldToken?: string;
+  onCancel: () => void;
+  onConfirm: (value: string) => void;
+  onClear: () => void;
+}
+
+//FIXME: merge UpdateTokenModal with SetTokenNewInstanceModal
+export function UpdateTokenModal({
+  onCancel,
+  onClear,
+  onConfirm,
+  oldToken,
+}: UpdateTokenModalProps): VNode {
+  type State = { old_token: string; new_token: string; repeat_token: string };
+  const [form, setValue] = useState<Partial<State>>({
+    old_token: "",
+    new_token: "",
+    repeat_token: "",
+  });
+  const { i18n } = useTranslationContext();
+
+  const hasInputTheCorrectOldToken = oldToken && oldToken !== form.old_token;
+  const errors = {
+    old_token: hasInputTheCorrectOldToken
+      ? i18n.str`is not the same as the current access token`
+      : undefined,
+    new_token: !form.new_token
+      ? i18n.str`cannot be empty`
+      : form.new_token === form.old_token
+      ? i18n.str`cannot be the same as the old token`
+      : undefined,
+    repeat_token:
+      form.new_token !== form.repeat_token
+        ? i18n.str`is not the same`
+        : undefined,
+  };
+
+  const hasErrors = Object.keys(errors).some(
+    (k) => (errors as any)[k] !== undefined,
+  );
+
+  const instance = useInstanceContext();
+
+  const text = i18n.str`You are updating the access token from instance with 
id ${instance.id}`;
+
+  return (
+    <ClearConfirmModal
+      description={text}
+      onCancel={onCancel}
+      onConfirm={!hasErrors ? () => onConfirm(form.new_token!) : undefined}
+      onClear={!hasInputTheCorrectOldToken && oldToken ? onClear : undefined}
+    >
+      <div class="columns">
+        <div class="column" />
+        <div class="column is-four-fifths">
+          <FormProvider errors={errors} object={form} valueHandler={setValue}>
+            {oldToken && (
+              <Input<State>
+                name="old_token"
+                label={i18n.str`Old access token`}
+                tooltip={i18n.str`access token currently in use`}
+                inputType="password"
+              />
+            )}
+            <Input<State>
+              name="new_token"
+              label={i18n.str`New access token`}
+              tooltip={i18n.str`next access token to be used`}
+              inputType="password"
+            />
+            <Input<State>
+              name="repeat_token"
+              label={i18n.str`Repeat access token`}
+              tooltip={i18n.str`confirm the same access token`}
+              inputType="password"
+            />
+          </FormProvider>
+          <p>
+            <i18n.Translate>
+              Clearing the access token will mean public access to the instance
+            </i18n.Translate>
+          </p>
+        </div>
+        <div class="column" />
+      </div>
+    </ClearConfirmModal>
+  );
+}
+
+export function SetTokenNewInstanceModal({
+  onCancel,
+  onClear,
+  onConfirm,
+}: UpdateTokenModalProps): VNode {
+  type State = { old_token: string; new_token: string; repeat_token: string };
+  const [form, setValue] = useState<Partial<State>>({
+    new_token: "",
+    repeat_token: "",
+  });
+  const { i18n } = useTranslationContext();
+
+  const errors = {
+    new_token: !form.new_token
+      ? i18n.str`cannot be empty`
+      : form.new_token === form.old_token
+      ? i18n.str`cannot be the same as the old access token`
+      : undefined,
+    repeat_token:
+      form.new_token !== form.repeat_token
+        ? i18n.str`is not the same`
+        : undefined,
+  };
+
+  const hasErrors = Object.keys(errors).some(
+    (k) => (errors as any)[k] !== undefined,
+  );
+
+  return (
+    <div class="modal is-active">
+      <div class="modal-background " onClick={onCancel} />
+      <div class="modal-card">
+        <header class="modal-card-head">
+          <p class="modal-card-title">{i18n.str`You are setting the access 
token for the new instance`}</p>
+          <button class="delete " aria-label="close" onClick={onCancel} />
+        </header>
+        <section class="modal-card-body is-main-section">
+          <div class="columns">
+            <div class="column" />
+            <div class="column is-four-fifths">
+              <FormProvider
+                errors={errors}
+                object={form}
+                valueHandler={setValue}
+              >
+                <Input<State>
+                  name="new_token"
+                  label={i18n.str`New access token`}
+                  tooltip={i18n.str`next access token to be used`}
+                  inputType="password"
+                />
+                <Input<State>
+                  name="repeat_token"
+                  label={i18n.str`Repeat access token`}
+                  tooltip={i18n.str`confirm the same access token`}
+                  inputType="password"
+                />
+              </FormProvider>
+              <p>
+                <i18n.Translate>
+                  With external authorization method no check will be done by
+                  the merchant backend
+                </i18n.Translate>
+              </p>
+            </div>
+            <div class="column" />
+          </div>
+        </section>
+        <footer class="modal-card-foot">
+          {onClear && (
+            <button
+              class="button is-danger"
+              onClick={onClear}
+              disabled={onClear === undefined}
+            >
+              <i18n.Translate>Set external authorization</i18n.Translate>
+            </button>
+          )}
+          <div class="buttons is-right" style={{ width: "100%" }}>
+            <button class="button " onClick={onCancel}>
+              <i18n.Translate>Cancel</i18n.Translate>
+            </button>
+            <button
+              class="button is-info"
+              onClick={() => onConfirm(form.new_token!)}
+              disabled={hasErrors}
+            >
+              <i18n.Translate>Set access token</i18n.Translate>
+            </button>
+          </div>
+        </footer>
+      </div>
+      <button
+        class="modal-close is-large "
+        aria-label="close"
+        onClick={onCancel}
+      />
+    </div>
+  );
+}
+
+export function LoadingModal({ onCancel }: { onCancel: () => void }): VNode {
+  const { i18n } = useTranslationContext();
+  return (
+    <div class="modal is-active">
+      <div class="modal-background " onClick={onCancel} />
+      <div class="modal-card">
+        <header class="modal-card-head">
+          <p class="modal-card-title">
+            <i18n.Translate>Operation in progress...</i18n.Translate>
+          </p>
+        </header>
+        <section class="modal-card-body">
+          <div class="columns">
+            <div class="column" />
+            <Spinner />
+            <div class="column" />
+          </div>
+          <p>{i18n.str`The operation will be automatically canceled after 
${DEFAULT_REQUEST_TIMEOUT} seconds`}</p>
+        </section>
+        <footer class="modal-card-foot">
+          <div class="buttons is-right" style={{ width: "100%" }}>
+            <button class="button " onClick={onCancel}>
+              <i18n.Translate>Cancel</i18n.Translate>
+            </button>
+          </div>
+        </footer>
+      </div>
+      <button
+        class="modal-close is-large "
+        aria-label="close"
+        onClick={onCancel}
+      />
+    </div>
+  );
+}
diff --git 
a/packages/auditor-backoffice-ui/src/components/notifications/CreatedSuccessfully.tsx
 
b/packages/auditor-backoffice-ui/src/components/notifications/CreatedSuccessfully.tsx
new file mode 100644
index 000000000..073382fb1
--- /dev/null
+++ 
b/packages/auditor-backoffice-ui/src/components/notifications/CreatedSuccessfully.tsx
@@ -0,0 +1,57 @@
+/*
+ This file is part of GNU Taler
+ (C) 2021-2023 Taler Systems S.A.
+
+ GNU Taler is free software; you can redistribute it and/or modify it under the
+ terms of the GNU General Public License as published by the Free Software
+ Foundation; either version 3, or (at your option) any later version.
+
+ GNU Taler is distributed in the hope that it will be useful, but WITHOUT ANY
+ WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
+ A PARTICULAR PURPOSE.  See the GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License along with
+ GNU Taler; see the file COPYING.  If not, see <http://www.gnu.org/licenses/>
+ */
+/**
+ *
+ * @author Sebastian Javier Marchano (sebasjm)
+ */
+import { ComponentChildren, h, VNode } from "preact";
+
+interface Props {
+  onCreateAnother?: () => void;
+  onConfirm: () => void;
+  children: ComponentChildren;
+}
+
+export function CreatedSuccessfully({
+  children,
+  onConfirm,
+  onCreateAnother,
+}: Props): VNode {
+  return (
+    <div class="columns is-fullwidth is-vcentered mt-3">
+      <div class="column" />
+      <div class="column is-four-fifths">
+        <div class="card">
+          <header class="card-header has-background-success">
+            <p class="card-header-title has-text-white-ter">Success.</p>
+          </header>
+          <div class="card-content">{children}</div>
+        </div>
+        <div class="buttons is-right">
+          {onCreateAnother && (
+            <button class="button is-info" onClick={onCreateAnother}>
+              Create another
+            </button>
+          )}
+          <button class="button is-info" onClick={onConfirm}>
+            Continue
+          </button>
+        </div>
+      </div>
+      <div class="column" />
+    </div>
+  );
+}
diff --git 
a/packages/auditor-backoffice-ui/src/components/notifications/Notifications.stories.tsx
 
b/packages/auditor-backoffice-ui/src/components/notifications/Notifications.stories.tsx
new file mode 100644
index 000000000..af594de0f
--- /dev/null
+++ 
b/packages/auditor-backoffice-ui/src/components/notifications/Notifications.stories.tsx
@@ -0,0 +1,62 @@
+/*
+ This file is part of GNU Taler
+ (C) 2021-2023 Taler Systems S.A.
+
+ GNU Taler is free software; you can redistribute it and/or modify it under the
+ terms of the GNU General Public License as published by the Free Software
+ Foundation; either version 3, or (at your option) any later version.
+
+ GNU Taler is distributed in the hope that it will be useful, but WITHOUT ANY
+ WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
+ A PARTICULAR PURPOSE.  See the GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License along with
+ GNU Taler; see the file COPYING.  If not, see <http://www.gnu.org/licenses/>
+ */
+
+/**
+ *
+ * @author Sebastian Javier Marchano (sebasjm)
+ */
+
+import { h } from "preact";
+import { Notifications } from "./index.js";
+
+export default {
+  title: "Components/Notification",
+  component: Notifications,
+  argTypes: {
+    removeNotification: { action: "removeNotification" },
+  },
+};
+
+export const Info = (a: any) => <Notifications {...a} />;
+Info.args = {
+  notifications: [
+    {
+      message: "Title",
+      description: "Some large description",
+      type: "INFO",
+    },
+  ],
+};
+export const Warn = (a: any) => <Notifications {...a} />;
+Warn.args = {
+  notifications: [
+    {
+      message: "Title",
+      description: "Some large description",
+      type: "WARN",
+    },
+  ],
+};
+export const Error = (a: any) => <Notifications {...a} />;
+Error.args = {
+  notifications: [
+    {
+      message: "Title",
+      description: "Some large description",
+      type: "ERROR",
+    },
+  ],
+};
diff --git 
a/packages/auditor-backoffice-ui/src/components/notifications/index.tsx 
b/packages/auditor-backoffice-ui/src/components/notifications/index.tsx
new file mode 100644
index 000000000..235c75577
--- /dev/null
+++ b/packages/auditor-backoffice-ui/src/components/notifications/index.tsx
@@ -0,0 +1,65 @@
+/*
+ This file is part of GNU Taler
+ (C) 2021-2023 Taler Systems S.A.
+
+ GNU Taler is free software; you can redistribute it and/or modify it under the
+ terms of the GNU General Public License as published by the Free Software
+ Foundation; either version 3, or (at your option) any later version.
+
+ GNU Taler is distributed in the hope that it will be useful, but WITHOUT ANY
+ WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
+ A PARTICULAR PURPOSE.  See the GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License along with
+ GNU Taler; see the file COPYING.  If not, see <http://www.gnu.org/licenses/>
+ */
+
+/**
+ *
+ * @author Sebastian Javier Marchano (sebasjm)
+ */
+
+import { h, VNode } from "preact";
+import { MessageType, Notification } from "../../utils/types.js";
+
+interface Props {
+  notifications: Notification[];
+  removeNotification?: (n: Notification) => void;
+}
+
+function messageStyle(type: MessageType): string {
+  switch (type) {
+    case "INFO":
+      return "message is-info";
+    case "WARN":
+      return "message is-warning";
+    case "ERROR":
+      return "message is-danger";
+    case "SUCCESS":
+      return "message is-success";
+    default:
+      return "message";
+  }
+}
+
+export function Notifications({
+  notifications,
+  removeNotification,
+}: Props): VNode {
+  return (
+    <div class="toast">
+      {notifications.map((n, i) => (
+        <article key={i} class={messageStyle(n.type)}>
+          <div class="message-header">
+            <p>{n.message}</p>
+            <button
+              class="delete"
+              onClick={() => removeNotification && removeNotification(n)}
+            />
+          </div>
+          {n.description && <div class="message-body">{n.description}</div>}
+        </article>
+      ))}
+    </div>
+  );
+}
diff --git 
a/packages/auditor-backoffice-ui/src/components/picker/DatePicker.tsx 
b/packages/auditor-backoffice-ui/src/components/picker/DatePicker.tsx
new file mode 100644
index 000000000..0bc629d46
--- /dev/null
+++ b/packages/auditor-backoffice-ui/src/components/picker/DatePicker.tsx
@@ -0,0 +1,349 @@
+/*
+ This file is part of GNU Taler
+ (C) 2021-2023 Taler Systems S.A.
+
+ GNU Taler is free software; you can redistribute it and/or modify it under the
+ terms of the GNU General Public License as published by the Free Software
+ Foundation; either version 3, or (at your option) any later version.
+
+ GNU Taler is distributed in the hope that it will be useful, but WITHOUT ANY
+ WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
+ A PARTICULAR PURPOSE.  See the GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License along with
+ GNU Taler; see the file COPYING.  If not, see <http://www.gnu.org/licenses/>
+ */
+
+/**
+ *
+ * @author Sebastian Javier Marchano (sebasjm)
+ */
+
+import { h, Component } from "preact";
+
+interface Props {
+  closeFunction?: () => void;
+  dateReceiver?: (d: Date) => void;
+  opened?: boolean;
+}
+interface State {
+  displayedMonth: number;
+  displayedYear: number;
+  selectYearMode: boolean;
+  currentDate: Date;
+}
+
+// inspired by https://codepen.io/m4r1vs/pen/MOOxyE
+export class DatePicker extends Component<Props, State> {
+  closeDatePicker() {
+    this.props.closeFunction && this.props.closeFunction(); // Function gets 
passed by parent
+  }
+
+  /**
+   * Gets fired when a day gets clicked.
+   * @param {object} e The event thrown by the <span /> element clicked
+   */
+  dayClicked(e: any) {
+    const element = e.target; // the actual element clicked
+
+    if (element.innerHTML === "") return false; // don't continue if <span /> 
empty
+
+    // get date from clicked element (gets attached when rendered)
+    const date = new Date(element.getAttribute("data-value"));
+
+    // update the state
+    this.setState({ currentDate: date });
+    this.passDateToParent(date);
+  }
+
+  /**
+   * returns days in month as array
+   * @param {number} month the month to display
+   * @param {number} year the year to display
+   */
+  getDaysByMonth(month: number, year: number) {
+    const calendar = [];
+
+    const date = new Date(year, month, 1); // month to display
+
+    const firstDay = new Date(year, month, 1).getDay(); // first weekday of 
month
+    const lastDate = new Date(year, month + 1, 0).getDate(); // last date of 
month
+
+    let day: number | null = 0;
+
+    // the calendar is 7*6 fields big, so 42 loops
+    for (let i = 0; i < 42; i++) {
+      if (i >= firstDay && day !== null) day = day + 1;
+      if (day !== null && day > lastDate) day = null;
+
+      // append the calendar Array
+      calendar.push({
+        day: day === 0 || day === null ? null : day, // null or number
+        date: day === 0 || day === null ? null : new Date(year, month, day), 
// null or Date()
+        today:
+          day === now.getDate() &&
+          month === now.getMonth() &&
+          year === now.getFullYear(), // boolean
+      });
+    }
+
+    return calendar;
+  }
+
+  /**
+   * Display previous month by updating state
+   */
+  displayPrevMonth() {
+    if (this.state.displayedMonth <= 0) {
+      this.setState({
+        displayedMonth: 11,
+        displayedYear: this.state.displayedYear - 1,
+      });
+    } else {
+      this.setState({
+        displayedMonth: this.state.displayedMonth - 1,
+      });
+    }
+  }
+
+  /**
+   * Display next month by updating state
+   */
+  displayNextMonth() {
+    if (this.state.displayedMonth >= 11) {
+      this.setState({
+        displayedMonth: 0,
+        displayedYear: this.state.displayedYear + 1,
+      });
+    } else {
+      this.setState({
+        displayedMonth: this.state.displayedMonth + 1,
+      });
+    }
+  }
+
+  /**
+   * Display the selected month (gets fired when clicking on the date string)
+   */
+  displaySelectedMonth() {
+    if (this.state.selectYearMode) {
+      this.toggleYearSelector();
+    } else {
+      if (!this.state.currentDate) return false;
+      this.setState({
+        displayedMonth: this.state.currentDate.getMonth(),
+        displayedYear: this.state.currentDate.getFullYear(),
+      });
+    }
+  }
+
+  toggleYearSelector() {
+    this.setState({ selectYearMode: !this.state.selectYearMode });
+  }
+
+  changeDisplayedYear(e: any) {
+    const element = e.target;
+    this.toggleYearSelector();
+    this.setState({
+      displayedYear: parseInt(element.innerHTML, 10),
+      displayedMonth: 0,
+    });
+  }
+
+  /**
+   * Pass the selected date to parent when 'OK' is clicked
+   */
+  passSavedDateDateToParent() {
+    this.passDateToParent(this.state.currentDate);
+  }
+  passDateToParent(date: Date) {
+    if (typeof this.props.dateReceiver === "function")
+      this.props.dateReceiver(date);
+    this.closeDatePicker();
+  }
+
+  componentDidUpdate() {
+    if (this.state.selectYearMode) {
+      document.getElementsByClassName("selected")[0].scrollIntoView(); // 
works in every browser incl. IE, replace with scrollIntoViewIfNeeded when 
browsers support it
+    }
+  }
+
+  constructor() {
+    super();
+
+    this.closeDatePicker = this.closeDatePicker.bind(this);
+    this.dayClicked = this.dayClicked.bind(this);
+    this.displayNextMonth = this.displayNextMonth.bind(this);
+    this.displayPrevMonth = this.displayPrevMonth.bind(this);
+    this.getDaysByMonth = this.getDaysByMonth.bind(this);
+    this.changeDisplayedYear = this.changeDisplayedYear.bind(this);
+    this.passDateToParent = this.passDateToParent.bind(this);
+    this.toggleYearSelector = this.toggleYearSelector.bind(this);
+    this.displaySelectedMonth = this.displaySelectedMonth.bind(this);
+
+    this.state = {
+      currentDate: now,
+      displayedMonth: now.getMonth(),
+      displayedYear: now.getFullYear(),
+      selectYearMode: false,
+    };
+  }
+
+  render() {
+    const { currentDate, displayedMonth, displayedYear, selectYearMode } =
+      this.state;
+
+    return (
+      <div>
+        <div class={`datePicker ${this.props.opened && "datePicker--opened"}`}>
+          <div class="datePicker--titles">
+            <h3
+              style={{
+                color: selectYearMode
+                  ? "rgba(255,255,255,.87)"
+                  : "rgba(255,255,255,.57)",
+              }}
+              onClick={this.toggleYearSelector}
+            >
+              {currentDate.getFullYear()}
+            </h3>
+            <h2
+              style={{
+                color: !selectYearMode
+                  ? "rgba(255,255,255,.87)"
+                  : "rgba(255,255,255,.57)",
+              }}
+              onClick={this.displaySelectedMonth}
+            >
+              {dayArr[currentDate.getDay()]},{" "}
+              {monthArrShort[currentDate.getMonth()]} {currentDate.getDate()}
+            </h2>
+          </div>
+
+          {!selectYearMode && (
+            <nav>
+              <span onClick={this.displayPrevMonth} class="icon">
+                <i
+                  style={{ transform: "rotate(180deg)" }}
+                  class="mdi mdi-forward"
+                />
+              </span>
+              <h4>
+                {monthArrShortFull[displayedMonth]} {displayedYear}
+              </h4>
+              <span onClick={this.displayNextMonth} class="icon">
+                <i class="mdi mdi-forward" />
+              </span>
+            </nav>
+          )}
+
+          <div class="datePicker--scroll">
+            {!selectYearMode && (
+              <div class="datePicker--calendar">
+                <div class="datePicker--dayNames">
+                  {["S", "M", "T", "W", "T", "F", "S"].map((day, i) => (
+                    <span key={i}>{day}</span>
+                  ))}
+                </div>
+
+                <div onClick={this.dayClicked} class="datePicker--days">
+                  {/*
+                  Loop through the calendar object returned by 
getDaysByMonth().
+                */}
+
+                  {this.getDaysByMonth(
+                    this.state.displayedMonth,
+                    this.state.displayedYear,
+                  ).map((day) => {
+                    let selected = false;
+
+                    if (currentDate && day.date)
+                      selected =
+                        currentDate.toLocaleDateString() ===
+                        day.date.toLocaleDateString();
+
+                    return (
+                      <span
+                        key={day.day}
+                        class={
+                          (day.today ? "datePicker--today " : "") +
+                          (selected ? "datePicker--selected" : "")
+                        }
+                        disabled={!day.date}
+                        data-value={day.date}
+                      >
+                        {day.day}
+                      </span>
+                    );
+                  })}
+                </div>
+              </div>
+            )}
+
+            {selectYearMode && (
+              <div class="datePicker--selectYear">
+                {yearArr.map((year) => (
+                  <span
+                    key={year}
+                    class={year === displayedYear ? "selected" : ""}
+                    onClick={this.changeDisplayedYear}
+                  >
+                    {year}
+                  </span>
+                ))}
+              </div>
+            )}
+          </div>
+        </div>
+
+        <div
+          class="datePicker--background"
+          onClick={this.closeDatePicker}
+          style={{
+            display: this.props.opened ? "block" : "none",
+          }}
+        />
+      </div>
+    );
+  }
+}
+
+const monthArrShortFull = [
+  "January",
+  "February",
+  "March",
+  "April",
+  "May",
+  "June",
+  "July",
+  "August",
+  "September",
+  "October",
+  "November",
+  "December",
+];
+
+const monthArrShort = [
+  "Jan",
+  "Feb",
+  "Mar",
+  "Apr",
+  "May",
+  "Jun",
+  "Jul",
+  "Aug",
+  "Sep",
+  "Oct",
+  "Nov",
+  "Dec",
+];
+
+const dayArr = ["Sun", "Mon", "Tue", "Wed", "Thu", "Fri", "Sat"];
+
+const now = new Date();
+
+const yearArr: number[] = [];
+
+for (let i = 2010; i <= now.getFullYear() + 10; i++) {
+  yearArr.push(i);
+}
diff --git 
a/packages/auditor-backoffice-ui/src/components/picker/DurationPicker.stories.tsx
 
b/packages/auditor-backoffice-ui/src/components/picker/DurationPicker.stories.tsx
new file mode 100644
index 000000000..8f74d55ac
--- /dev/null
+++ 
b/packages/auditor-backoffice-ui/src/components/picker/DurationPicker.stories.tsx
@@ -0,0 +1,55 @@
+/*
+ This file is part of GNU Taler
+ (C) 2021-2023 Taler Systems S.A.
+
+ GNU Taler is free software; you can redistribute it and/or modify it under the
+ terms of the GNU General Public License as published by the Free Software
+ Foundation; either version 3, or (at your option) any later version.
+
+ GNU Taler is distributed in the hope that it will be useful, but WITHOUT ANY
+ WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
+ A PARTICULAR PURPOSE.  See the GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License along with
+ GNU Taler; see the file COPYING.  If not, see <http://www.gnu.org/licenses/>
+ */
+
+/**
+ *
+ * @author Sebastian Javier Marchano (sebasjm)
+ */
+
+import { h, FunctionalComponent } from "preact";
+import { useState } from "preact/hooks";
+import { DurationPicker as TestedComponent } from "./DurationPicker.js";
+
+export default {
+  title: "Components/Picker/Duration",
+  component: TestedComponent,
+  argTypes: {
+    onCreate: { action: "onCreate" },
+    goBack: { action: "goBack" },
+  },
+};
+
+function createExample<Props>(
+  Component: FunctionalComponent<Props>,
+  props: Partial<Props>,
+) {
+  const r = (args: any) => <Component {...args} />;
+  r.args = props;
+  return r;
+}
+
+export const Example = createExample(TestedComponent, {
+  days: true,
+  minutes: true,
+  hours: true,
+  seconds: true,
+  value: 10000000,
+});
+
+export const WithState = () => {
+  const [v, s] = useState<number>(1000000);
+  return <TestedComponent value={v} onChange={s} days minutes hours seconds />;
+};
diff --git 
a/packages/auditor-backoffice-ui/src/components/picker/DurationPicker.tsx 
b/packages/auditor-backoffice-ui/src/components/picker/DurationPicker.tsx
new file mode 100644
index 000000000..ba003cce5
--- /dev/null
+++ b/packages/auditor-backoffice-ui/src/components/picker/DurationPicker.tsx
@@ -0,0 +1,211 @@
+/*
+ This file is part of GNU Taler
+ (C) 2021-2023 Taler Systems S.A.
+
+ GNU Taler is free software; you can redistribute it and/or modify it under the
+ terms of the GNU General Public License as published by the Free Software
+ Foundation; either version 3, or (at your option) any later version.
+
+ GNU Taler is distributed in the hope that it will be useful, but WITHOUT ANY
+ WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
+ A PARTICULAR PURPOSE.  See the GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License along with
+ GNU Taler; see the file COPYING.  If not, see <http://www.gnu.org/licenses/>
+ */
+
+/**
+ *
+ * @author Sebastian Javier Marchano (sebasjm)
+ */
+
+import { useTranslationContext } from "@gnu-taler/web-util/browser";
+import { h, VNode } from "preact";
+import { useState } from "preact/hooks";
+import "../../scss/DurationPicker.scss";
+
+export interface Props {
+  hours?: boolean;
+  minutes?: boolean;
+  seconds?: boolean;
+  days?: boolean;
+  onChange: (value: number) => void;
+  value: number;
+}
+
+// inspiration taken from https://github.com/flurmbo/react-duration-picker
+export function DurationPicker({
+  days,
+  hours,
+  minutes,
+  seconds,
+  onChange,
+  value,
+}: Props): VNode {
+  const ss = 1000;
+  const ms = ss * 60;
+  const hs = ms * 60;
+  const ds = hs * 24;
+  const { i18n } = useTranslationContext();
+
+  return (
+    <div class="rdp-picker">
+      {days && (
+        <DurationColumn
+          unit={i18n.str`days`}
+          max={99}
+          value={Math.floor(value / ds)}
+          onDecrease={value >= ds ? () => onChange(value - ds) : undefined}
+          onIncrease={value < 99 * ds ? () => onChange(value + ds) : undefined}
+          onChange={(diff) => onChange(value + diff * ds)}
+        />
+      )}
+      {hours && (
+        <DurationColumn
+          unit={i18n.str`hours`}
+          max={23}
+          min={1}
+          value={Math.floor(value / hs) % 24}
+          onDecrease={value >= hs ? () => onChange(value - hs) : undefined}
+          onIncrease={value < 99 * ds ? () => onChange(value + hs) : undefined}
+          onChange={(diff) => onChange(value + diff * hs)}
+        />
+      )}
+      {minutes && (
+        <DurationColumn
+          unit={i18n.str`minutes`}
+          max={59}
+          min={1}
+          value={Math.floor(value / ms) % 60}
+          onDecrease={value >= ms ? () => onChange(value - ms) : undefined}
+          onIncrease={value < 99 * ds ? () => onChange(value + ms) : undefined}
+          onChange={(diff) => onChange(value + diff * ms)}
+        />
+      )}
+      {seconds && (
+        <DurationColumn
+          unit={i18n.str`seconds`}
+          max={59}
+          value={Math.floor(value / ss) % 60}
+          onDecrease={value >= ss ? () => onChange(value - ss) : undefined}
+          onIncrease={value < 99 * ds ? () => onChange(value + ss) : undefined}
+          onChange={(diff) => onChange(value + diff * ss)}
+        />
+      )}
+    </div>
+  );
+}
+
+interface ColProps {
+  unit: string;
+  min?: number;
+  max: number;
+  value: number;
+  onIncrease?: () => void;
+  onDecrease?: () => void;
+  onChange?: (diff: number) => void;
+}
+
+function InputNumber({
+  initial,
+  onChange,
+}: {
+  initial: number;
+  onChange: (n: number) => void;
+}) {
+  const [value, handler] = useState<{ v: string }>({
+    v: toTwoDigitString(initial),
+  });
+
+  return (
+    <input
+      value={value.v}
+      onBlur={(e) => onChange(parseInt(value.v, 10))}
+      onInput={(e) => {
+        e.preventDefault();
+        const n = Number.parseInt(e.currentTarget.value, 10);
+        if (isNaN(n)) return handler({ v: toTwoDigitString(initial) });
+        return handler({ v: toTwoDigitString(n) });
+      }}
+      style={{
+        width: 50,
+        border: "none",
+        fontSize: "inherit",
+        background: "inherit",
+      }}
+    />
+  );
+}
+
+function DurationColumn({
+  unit,
+  min = 0,
+  max,
+  value,
+  onIncrease,
+  onDecrease,
+  onChange,
+}: ColProps): VNode {
+  const cellHeight = 35;
+  return (
+    <div class="rdp-column-container">
+      <div class="rdp-masked-div">
+        <hr class="rdp-reticule" style={{ top: cellHeight * 2 - 1 }} />
+        <hr class="rdp-reticule" style={{ top: cellHeight * 3 - 1 }} />
+
+        <div class="rdp-column" style={{ top: 0 }}>
+          <div class="rdp-cell" key={value - 2}>
+            {onDecrease && (
+              <button
+                style={{ width: "100%", textAlign: "center", margin: 5 }}
+                onClick={onDecrease}
+              >
+                <span class="icon">
+                  <i class="mdi mdi-chevron-up" />
+                </span>
+              </button>
+            )}
+          </div>
+          <div class="rdp-cell" key={value - 1}>
+            {value > min ? toTwoDigitString(value - 1) : ""}
+          </div>
+          <div class="rdp-cell rdp-center" key={value}>
+            {onChange ? (
+              <InputNumber
+                initial={value}
+                onChange={(n) => onChange(n - value)}
+              />
+            ) : (
+              toTwoDigitString(value)
+            )}
+            <div>{unit}</div>
+          </div>
+
+          <div class="rdp-cell" key={value + 1}>
+            {value < max ? toTwoDigitString(value + 1) : ""}
+          </div>
+
+          <div class="rdp-cell" key={value + 2}>
+            {onIncrease && (
+              <button
+                style={{ width: "100%", textAlign: "center", margin: 5 }}
+                onClick={onIncrease}
+              >
+                <span class="icon">
+                  <i class="mdi mdi-chevron-down" />
+                </span>
+              </button>
+            )}
+          </div>
+        </div>
+      </div>
+    </div>
+  );
+}
+
+function toTwoDigitString(n: number) {
+  if (n < 10) {
+    return `0${n}`;
+  }
+  return `${n}`;
+}
diff --git 
a/packages/auditor-backoffice-ui/src/components/product/InventoryProductForm.stories.tsx
 
b/packages/auditor-backoffice-ui/src/components/product/InventoryProductForm.stories.tsx
new file mode 100644
index 000000000..2d5a54cde
--- /dev/null
+++ 
b/packages/auditor-backoffice-ui/src/components/product/InventoryProductForm.stories.tsx
@@ -0,0 +1,62 @@
+/*
+ This file is part of GNU Taler
+ (C) 2021-2023 Taler Systems S.A.
+
+ GNU Taler is free software; you can redistribute it and/or modify it under the
+ terms of the GNU General Public License as published by the Free Software
+ Foundation; either version 3, or (at your option) any later version.
+
+ GNU Taler is distributed in the hope that it will be useful, but WITHOUT ANY
+ WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
+ A PARTICULAR PURPOSE.  See the GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License along with
+ GNU Taler; see the file COPYING.  If not, see <http://www.gnu.org/licenses/>
+ */
+
+/**
+ *
+ * @author Sebastian Javier Marchano (sebasjm)
+ */
+
+import { h, VNode, FunctionalComponent } from "preact";
+import { InventoryProductForm as TestedComponent } from 
"./InventoryProductForm.js";
+
+export default {
+  title: "Components/Product/Add",
+  component: TestedComponent,
+  argTypes: {
+    onAddProduct: { action: "onAddProduct" },
+  },
+};
+
+function createExample<Props>(
+  Component: FunctionalComponent<Props>,
+  props: Partial<Props>,
+) {
+  const r = (args: any) => <Component {...args} />;
+  r.args = props;
+  return r;
+}
+
+export const WithASimpleList = createExample(TestedComponent, {
+  inventory: [
+    {
+      id: "this id",
+      description: "this is the description",
+    } as any,
+  ],
+});
+
+export const WithAProductSelected = createExample(TestedComponent, {
+  inventory: [],
+  currentProducts: {
+    thisid: {
+      quantity: 1,
+      product: {
+        id: "asd",
+        description: "asdsadsad",
+      } as any,
+    },
+  },
+});
diff --git 
a/packages/auditor-backoffice-ui/src/components/product/InventoryProductForm.tsx
 
b/packages/auditor-backoffice-ui/src/components/product/InventoryProductForm.tsx
new file mode 100644
index 000000000..377d9c1ba
--- /dev/null
+++ 
b/packages/auditor-backoffice-ui/src/components/product/InventoryProductForm.tsx
@@ -0,0 +1,127 @@
+/*
+ This file is part of GNU Taler
+ (C) 2021-2023 Taler Systems S.A.
+
+ GNU Taler is free software; you can redistribute it and/or modify it under the
+ terms of the GNU General Public License as published by the Free Software
+ Foundation; either version 3, or (at your option) any later version.
+
+ GNU Taler is distributed in the hope that it will be useful, but WITHOUT ANY
+ WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
+ A PARTICULAR PURPOSE.  See the GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License along with
+ GNU Taler; see the file COPYING.  If not, see <http://www.gnu.org/licenses/>
+ */
+import { useTranslationContext } from "@gnu-taler/web-util/browser";
+import { h, VNode } from "preact";
+import { useState } from "preact/hooks";
+import { MerchantBackend, WithId } from "../../declaration.js";
+import { ProductMap } from "../../paths/instance/orders/create/CreatePage.js";
+import { FormErrors, FormProvider } from "../form/FormProvider.js";
+import { InputNumber } from "../form/InputNumber.js";
+import { InputSearchOnList } from "../form/InputSearchOnList.js";
+
+type Form = {
+  product: MerchantBackend.Products.ProductDetail & WithId;
+  quantity: number;
+};
+
+interface Props {
+  currentProducts: ProductMap;
+  onAddProduct: (
+    product: MerchantBackend.Products.ProductDetail & WithId,
+    quantity: number,
+  ) => void;
+  inventory: (MerchantBackend.Products.ProductDetail & WithId)[];
+}
+
+export function InventoryProductForm({
+  currentProducts,
+  onAddProduct,
+  inventory,
+}: Props): VNode {
+  const initialState = { quantity: 1 };
+  const [state, setState] = useState<Partial<Form>>(initialState);
+  const [errors, setErrors] = useState<FormErrors<Form>>({});
+
+  const { i18n } = useTranslationContext();
+
+  const productWithInfiniteStock =
+    state.product && state.product.total_stock === -1;
+
+  const submit = (): void => {
+    if (!state.product) {
+      setErrors({
+        product: i18n.str`You must enter a valid product identifier.`,
+      });
+      return;
+    }
+    if (productWithInfiniteStock) {
+      onAddProduct(state.product, 1);
+    } else {
+      if (!state.quantity || state.quantity <= 0) {
+        setErrors({ quantity: i18n.str`Quantity must be greater than 0!` });
+        return;
+      }
+      const currentStock =
+        state.product.total_stock -
+        state.product.total_lost -
+        state.product.total_sold;
+      const p = currentProducts[state.product.id];
+      if (p) {
+        if (state.quantity + p.quantity > currentStock) {
+          const left = currentStock - p.quantity;
+          setErrors({
+            quantity: i18n.str`This quantity exceeds remaining stock. 
Currently, only ${left} units remain unreserved in stock.`,
+          });
+          return;
+        }
+        onAddProduct(state.product, state.quantity + p.quantity);
+      } else {
+        if (state.quantity > currentStock) {
+          const left = currentStock;
+          setErrors({
+            quantity: i18n.str`This quantity exceeds remaining stock. 
Currently, only ${left} units remain unreserved in stock.`,
+          });
+          return;
+        }
+        onAddProduct(state.product, state.quantity);
+      }
+    }
+
+    setState(initialState);
+  };
+
+  return (
+    <FormProvider<Form> errors={errors} object={state} valueHandler={setState}>
+      <InputSearchOnList
+        label={i18n.str`Search product`}
+        selected={state.product}
+        onChange={(p) => setState((v) => ({ ...v, product: p }))}
+        list={inventory}
+        withImage
+      />
+      {state.product && (
+        <div class="columns mt-5">
+          <div class="column is-two-thirds">
+            {!productWithInfiniteStock && (
+              <InputNumber<Form>
+                name="quantity"
+                label={i18n.str`Quantity`}
+                tooltip={i18n.str`how many products will be added`}
+              />
+            )}
+          </div>
+          <div class="column">
+            <div class="buttons is-right">
+              <button class="button is-success" onClick={submit}>
+                <i18n.Translate>Add from inventory</i18n.Translate>
+              </button>
+            </div>
+          </div>
+        </div>
+      )}
+    </FormProvider>
+  );
+}
diff --git 
a/packages/auditor-backoffice-ui/src/components/product/NonInventoryProductForm.tsx
 
b/packages/auditor-backoffice-ui/src/components/product/NonInventoryProductForm.tsx
new file mode 100644
index 000000000..c6d280f94
--- /dev/null
+++ 
b/packages/auditor-backoffice-ui/src/components/product/NonInventoryProductForm.tsx
@@ -0,0 +1,215 @@
+/*
+ This file is part of GNU Taler
+ (C) 2021-2023 Taler Systems S.A.
+
+ GNU Taler is free software; you can redistribute it and/or modify it under the
+ terms of the GNU General Public License as published by the Free Software
+ Foundation; either version 3, or (at your option) any later version.
+
+ GNU Taler is distributed in the hope that it will be useful, but WITHOUT ANY
+ WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
+ A PARTICULAR PURPOSE.  See the GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License along with
+ GNU Taler; see the file COPYING.  If not, see <http://www.gnu.org/licenses/>
+ */
+import { useTranslationContext } from "@gnu-taler/web-util/browser";
+import { Fragment, h, VNode } from "preact";
+import { useCallback, useEffect, useState } from "preact/hooks";
+import * as yup from "yup";
+import { MerchantBackend } from "../../declaration.js";
+import { useListener } from "../../hooks/listener.js";
+import { NonInventoryProductSchema as schema } from "../../schemas/index.js";
+import { FormErrors, FormProvider } from "../form/FormProvider.js";
+import { Input } from "../form/Input.js";
+import { InputCurrency } from "../form/InputCurrency.js";
+import { InputImage } from "../form/InputImage.js";
+import { InputNumber } from "../form/InputNumber.js";
+import { InputTaxes } from "../form/InputTaxes.js";
+
+type Entity = MerchantBackend.Product;
+
+interface Props {
+  onAddProduct: (p: Entity) => Promise<void>;
+  productToEdit?: Entity;
+}
+export function NonInventoryProductFrom({
+  productToEdit,
+  onAddProduct,
+}: Props): VNode {
+  const [showCreateProduct, setShowCreateProduct] = useState(false);
+
+  const isEditing = !!productToEdit;
+
+  useEffect(() => {
+    setShowCreateProduct(isEditing);
+  }, [isEditing]);
+
+  const [submitForm, addFormSubmitter] = useListener<
+    Partial<MerchantBackend.Product> | undefined
+  >((result) => {
+    if (result) {
+      setShowCreateProduct(false);
+      return onAddProduct({
+        quantity: result.quantity || 0,
+        taxes: result.taxes || [],
+        description: result.description || "",
+        image: result.image || "",
+        price: result.price || "",
+        unit: result.unit || "",
+      });
+    }
+    return Promise.resolve();
+  });
+
+  const { i18n } = useTranslationContext();
+
+  return (
+    <Fragment>
+      <div class="buttons">
+        <button
+          class="button is-success"
+          data-tooltip={i18n.str`describe and add a product that is not in the 
inventory list`}
+          onClick={() => setShowCreateProduct(true)}
+        >
+          <i18n.Translate>Add custom product</i18n.Translate>
+        </button>
+      </div>
+      {showCreateProduct && (
+        <div class="modal is-active">
+          <div
+            class="modal-background "
+            onClick={() => setShowCreateProduct(false)}
+          />
+          <div class="modal-card">
+            <header class="modal-card-head">
+              <p class="modal-card-title">{i18n.str`Complete information of 
the product`}</p>
+              <button
+                class="delete "
+                aria-label="close"
+                onClick={() => setShowCreateProduct(false)}
+              />
+            </header>
+            <section class="modal-card-body">
+              <ProductForm
+                initial={productToEdit}
+                onSubscribe={addFormSubmitter}
+              />
+            </section>
+            <footer class="modal-card-foot">
+              <div class="buttons is-right" style={{ width: "100%" }}>
+                <button
+                  class="button "
+                  onClick={() => setShowCreateProduct(false)}
+                >
+                  <i18n.Translate>Cancel</i18n.Translate>
+                </button>
+                <button
+                  class="button is-info "
+                  disabled={!submitForm}
+                  onClick={submitForm}
+                >
+                  <i18n.Translate>Confirm</i18n.Translate>
+                </button>
+              </div>
+            </footer>
+          </div>
+          <button
+            class="modal-close is-large "
+            aria-label="close"
+            onClick={() => setShowCreateProduct(false)}
+          />
+        </div>
+      )}
+    </Fragment>
+  );
+}
+
+interface ProductProps {
+  onSubscribe: (c?: () => Entity | undefined) => void;
+  initial?: Partial<Entity>;
+}
+
+interface NonInventoryProduct {
+  quantity: number;
+  description: string;
+  unit: string;
+  price: string;
+  image: string;
+  taxes: MerchantBackend.Tax[];
+}
+
+export function ProductForm({ onSubscribe, initial }: ProductProps): VNode {
+  const [value, valueHandler] = useState<Partial<NonInventoryProduct>>({
+    taxes: [],
+    ...initial,
+  });
+  let errors: FormErrors<Entity> = {};
+  try {
+    schema.validateSync(value, { abortEarly: false });
+  } catch (err) {
+    if (err instanceof yup.ValidationError) {
+      const yupErrors = err.inner as yup.ValidationError[];
+      errors = yupErrors.reduce(
+        (prev, cur) =>
+          !cur.path ? prev : { ...prev, [cur.path]: cur.message },
+        {},
+      );
+    }
+  }
+
+  const submit = useCallback((): Entity | undefined => {
+    return value as MerchantBackend.Product;
+  }, [value]);
+
+  const hasErrors = Object.keys(errors).some(
+    (k) => (errors as any)[k] !== undefined,
+  );
+
+  useEffect(() => {
+    onSubscribe(hasErrors ? undefined : submit);
+  }, [submit, hasErrors]);
+
+  const { i18n } = useTranslationContext();
+
+  return (
+    <div>
+      <FormProvider<NonInventoryProduct>
+        name="product"
+        errors={errors}
+        object={value}
+        valueHandler={valueHandler}
+      >
+        <InputImage<NonInventoryProduct>
+          name="image"
+          label={i18n.str`Image`}
+          tooltip={i18n.str`photo of the product`}
+        />
+        <Input<NonInventoryProduct>
+          name="description"
+          inputType="multiline"
+          label={i18n.str`Description`}
+          tooltip={i18n.str`full product description`}
+        />
+        <Input<NonInventoryProduct>
+          name="unit"
+          label={i18n.str`Unit`}
+          tooltip={i18n.str`name of the product unit`}
+        />
+        <InputCurrency<NonInventoryProduct>
+          name="price"
+          label={i18n.str`Price`}
+          tooltip={i18n.str`amount in the current currency`}
+        />
+
+        <InputNumber<NonInventoryProduct>
+          name="quantity"
+          label={i18n.str`Quantity`}
+          tooltip={i18n.str`how many products will be added`}
+        />
+
+        <InputTaxes<NonInventoryProduct> name="taxes" label={i18n.str`Taxes`} 
/>
+      </FormProvider>
+    </div>
+  );
+}
diff --git 
a/packages/auditor-backoffice-ui/src/components/product/ProductForm.tsx 
b/packages/auditor-backoffice-ui/src/components/product/ProductForm.tsx
new file mode 100644
index 000000000..e91e8c876
--- /dev/null
+++ b/packages/auditor-backoffice-ui/src/components/product/ProductForm.tsx
@@ -0,0 +1,178 @@
+/*
+ This file is part of GNU Taler
+ (C) 2021-2023 Taler Systems S.A.
+
+ GNU Taler is free software; you can redistribute it and/or modify it under the
+ terms of the GNU General Public License as published by the Free Software
+ Foundation; either version 3, or (at your option) any later version.
+
+ GNU Taler is distributed in the hope that it will be useful, but WITHOUT ANY
+ WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
+ A PARTICULAR PURPOSE.  See the GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License along with
+ GNU Taler; see the file COPYING.  If not, see <http://www.gnu.org/licenses/>
+ */
+
+/**
+ *
+ * @author Sebastian Javier Marchano (sebasjm)
+ */
+
+import { useTranslationContext } from "@gnu-taler/web-util/browser";
+import { h } from "preact";
+import { useCallback, useEffect, useState } from "preact/hooks";
+import * as yup from "yup";
+import { useBackendContext } from "../../context/backend.js";
+import { MerchantBackend } from "../../declaration.js";
+import {
+  ProductCreateSchema as createSchema,
+  ProductUpdateSchema as updateSchema,
+} from "../../schemas/index.js";
+import { FormErrors, FormProvider } from "../form/FormProvider.js";
+import { Input } from "../form/Input.js";
+import { InputCurrency } from "../form/InputCurrency.js";
+import { InputImage } from "../form/InputImage.js";
+import { InputNumber } from "../form/InputNumber.js";
+import { InputStock, Stock } from "../form/InputStock.js";
+import { InputTaxes } from "../form/InputTaxes.js";
+import { InputWithAddon } from "../form/InputWithAddon.js";
+
+type Entity = MerchantBackend.Products.ProductDetail & { product_id: string };
+
+interface Props {
+  onSubscribe: (c?: () => Entity | undefined) => void;
+  initial?: Partial<Entity>;
+  alreadyExist?: boolean;
+}
+
+export function ProductForm({ onSubscribe, initial, alreadyExist }: Props) {
+  const [value, valueHandler] = useState<Partial<Entity & { stock: Stock }>>({
+    address: {},
+    description_i18n: {},
+    taxes: [],
+    next_restock: { t_s: "never" },
+    price: ":0",
+    ...initial,
+    stock:
+      !initial || initial.total_stock === -1
+        ? undefined
+        : {
+          current: initial.total_stock || 0,
+          lost: initial.total_lost || 0,
+          sold: initial.total_sold || 0,
+          address: initial.address,
+          nextRestock: initial.next_restock,
+        },
+  });
+  let errors: FormErrors<Entity> = {};
+
+  try {
+    (alreadyExist ? updateSchema : createSchema).validateSync(value, {
+      abortEarly: false,
+    });
+  } catch (err) {
+    if (err instanceof yup.ValidationError) {
+      const yupErrors = err.inner as yup.ValidationError[];
+      errors = yupErrors.reduce(
+        (prev, cur) =>
+          !cur.path ? prev : { ...prev, [cur.path]: cur.message },
+        {},
+      );
+    }
+  }
+  const hasErrors = Object.keys(errors).some(
+    (k) => (errors as any)[k] !== undefined,
+  );
+
+  const submit = useCallback((): Entity | undefined => {
+    const stock: Stock = (value as any).stock;
+
+    if (!stock) {
+      value.total_stock = -1;
+    } else {
+      value.total_stock = stock.current;
+      value.total_lost = stock.lost;
+      value.next_restock =
+        stock.nextRestock instanceof Date
+          ? { t_s: stock.nextRestock.getTime() / 1000 }
+          : stock.nextRestock;
+      value.address = stock.address;
+    }
+    delete (value as any).stock;
+
+    if (typeof value.minimum_age !== "undefined" && value.minimum_age < 1) {
+      delete value.minimum_age;
+    }
+
+    return value as MerchantBackend.Products.ProductDetail & {
+      product_id: string;
+    };
+  }, [value]);
+
+  useEffect(() => {
+    onSubscribe(hasErrors ? undefined : submit);
+  }, [submit, hasErrors]);
+
+  const { url: backendURL } = useBackendContext()
+  const { i18n } = useTranslationContext();
+
+  return (
+    <div>
+      <FormProvider<Entity>
+        name="product"
+        errors={errors}
+        object={value}
+        valueHandler={valueHandler}
+      >
+        {alreadyExist ? undefined : (
+          <InputWithAddon<Entity>
+            name="product_id"
+            addonBefore={`${backendURL}/product/`}
+            label={i18n.str`ID`}
+            tooltip={i18n.str`product identification to use in URLs (for 
internal use only)`}
+          />
+        )}
+        <InputImage<Entity>
+          name="image"
+          label={i18n.str`Image`}
+          tooltip={i18n.str`illustration of the product for customers`}
+        />
+        <Input<Entity>
+          name="description"
+          inputType="multiline"
+          label={i18n.str`Description`}
+          tooltip={i18n.str`product description for customers`}
+        />
+        <InputNumber<Entity>
+          name="minimum_age"
+          label={i18n.str`Age restriction`}
+          tooltip={i18n.str`is this product restricted for customer below 
certain age?`}
+          help={i18n.str`minimum age of the buyer`}
+        />
+        <Input<Entity>
+          name="unit"
+          label={i18n.str`Unit name`}
+          tooltip={i18n.str`unit describing quantity of product sold (e.g. 2 
kilograms, 5 liters, 3 items, 5 meters) for customers`}
+          help={i18n.str`exajmple: kg, items or liters`}
+        />
+        <InputCurrency<Entity>
+          name="price"
+          label={i18n.str`Price per unit`}
+          tooltip={i18n.str`sale price for customers, including taxes, for 
above units of the product`}
+        />
+        <InputStock
+          name="stock"
+          label={i18n.str`Stock`}
+          alreadyExist={alreadyExist}
+          tooltip={i18n.str`inventory for products with finite supply (for 
internal use only)`}
+        />
+        <InputTaxes<Entity>
+          name="taxes"
+          label={i18n.str`Taxes`}
+          tooltip={i18n.str`taxes included in the product price, exposed to 
customers`}
+        />
+      </FormProvider>
+    </div>
+  );
+}
diff --git 
a/packages/auditor-backoffice-ui/src/components/product/ProductList.tsx 
b/packages/auditor-backoffice-ui/src/components/product/ProductList.tsx
new file mode 100644
index 000000000..25751dd96
--- /dev/null
+++ b/packages/auditor-backoffice-ui/src/components/product/ProductList.tsx
@@ -0,0 +1,106 @@
+/*
+ This file is part of GNU Taler
+ (C) 2021-2023 Taler Systems S.A.
+
+ GNU Taler is free software; you can redistribute it and/or modify it under the
+ terms of the GNU General Public License as published by the Free Software
+ Foundation; either version 3, or (at your option) any later version.
+
+ GNU Taler is distributed in the hope that it will be useful, but WITHOUT ANY
+ WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
+ A PARTICULAR PURPOSE.  See the GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License along with
+ GNU Taler; see the file COPYING.  If not, see <http://www.gnu.org/licenses/>
+ */
+import { Amounts } from "@gnu-taler/taler-util";
+import { h, VNode } from "preact";
+import emptyImage from "../../assets/empty.png";
+import { useTranslationContext } from "@gnu-taler/web-util/browser";
+import { MerchantBackend } from "../../declaration.js";
+
+interface Props {
+  list: MerchantBackend.Product[];
+  actions?: {
+    name: string;
+    tooltip: string;
+    handler: (d: MerchantBackend.Product, index: number) => void;
+  }[];
+}
+export function ProductList({ list, actions = [] }: Props): VNode {
+  const { i18n } = useTranslationContext();
+  return (
+    <div class="table-container">
+      <table class="table is-fullwidth is-striped is-hoverable is-fullwidth">
+        <thead>
+          <tr>
+            <th>
+              <i18n.Translate>image</i18n.Translate>
+            </th>
+            <th>
+              <i18n.Translate>description</i18n.Translate>
+            </th>
+            <th>
+              <i18n.Translate>quantity</i18n.Translate>
+            </th>
+            <th>
+              <i18n.Translate>unit price</i18n.Translate>
+            </th>
+            <th>
+              <i18n.Translate>total price</i18n.Translate>
+            </th>
+            <th />
+          </tr>
+        </thead>
+        <tbody>
+          {list.map((entry, index) => {
+            const unitPrice = !entry.price ? "0" : entry.price;
+            const totalPrice = !entry.price
+              ? "0"
+              : Amounts.stringify(
+                  Amounts.mult(
+                    Amounts.parseOrThrow(entry.price),
+                    entry.quantity,
+                  ).amount,
+                );
+
+            return (
+              <tr key={index}>
+                <td>
+                  <img
+                    style={{ height: 32, width: 32 }}
+                    src={entry.image ? entry.image : emptyImage}
+                  />
+                </td>
+                <td>{entry.description}</td>
+                <td>
+                  {entry.quantity === 0
+                    ? "--"
+                    : `${entry.quantity} ${entry.unit}`}
+                </td>
+                <td>{unitPrice}</td>
+                <td>{totalPrice}</td>
+                <td class="is-actions-cell right-sticky">
+                  {actions.map((a, i) => {
+                    return (
+                      <div key={i} class="buttons is-right">
+                        <button
+                          class="button is-small is-danger has-tooltip-left"
+                          data-tooltip={a.tooltip}
+                          type="button"
+                          onClick={() => a.handler(entry, index)}
+                        >
+                          {a.name}
+                        </button>
+                      </div>
+                    );
+                  })}
+                </td>
+              </tr>
+            );
+          })}
+        </tbody>
+      </table>
+    </div>
+  );
+}
diff --git a/packages/auditor-backoffice-ui/src/context/backend.test.ts 
b/packages/auditor-backoffice-ui/src/context/backend.test.ts
new file mode 100644
index 000000000..359859819
--- /dev/null
+++ b/packages/auditor-backoffice-ui/src/context/backend.test.ts
@@ -0,0 +1,163 @@
+/*
+ This file is part of GNU Taler
+ (C) 2021-2023 Taler Systems S.A.
+
+ GNU Taler is free software; you can redistribute it and/or modify it under the
+ terms of the GNU General Public License as published by the Free Software
+ Foundation; either version 3, or (at your option) any later version.
+
+ GNU Taler is distributed in the hope that it will be useful, but WITHOUT ANY
+ WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
+ A PARTICULAR PURPOSE.  See the GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License along with
+ GNU Taler; see the file COPYING.  If not, see <http://www.gnu.org/licenses/>
+ */
+
+/**
+ *
+ * @author Sebastian Javier Marchano (sebasjm)
+ */
+
+import * as tests from "@gnu-taler/web-util/testing";
+import { ComponentChildren, h, VNode } from "preact";
+import { AccessToken, MerchantBackend } from "../declaration.js";
+import {
+  useAdminAPI,
+  useInstanceAPI,
+  useManagementAPI,
+} from "../hooks/instance.js";
+import { expect } from "chai";
+import { ApiMockEnvironment } from "../hooks/testing.js";
+import {
+  API_CREATE_INSTANCE,
+  API_NEW_LOGIN,
+  API_UPDATE_CURRENT_INSTANCE_AUTH,
+  API_UPDATE_INSTANCE_AUTH_BY_ID,
+} from "../hooks/urls.js";
+
+interface TestingContextProps {
+  children?: ComponentChildren;
+}
+
+describe("backend context api ", () => {
+  it("should use new token after updating the instance token in the settings 
as user", async () => {
+    const env = new ApiMockEnvironment();
+
+    const hookBehavior = await tests.hookBehaveLikeThis(
+      () => {
+        const instance = useInstanceAPI();
+        const management = useManagementAPI("default");
+        const admin = useAdminAPI();
+
+        return { instance, management, admin };
+      },
+      {},
+      [
+        ({ instance, management, admin }) => {
+          env.addRequestExpectation(API_UPDATE_INSTANCE_AUTH_BY_ID("default"), 
{
+            request: {
+              method: "token",
+              token: "another_token",
+            },
+            response: {
+              name: "instance_name",
+            } as MerchantBackend.Instances.QueryInstancesResponse,
+          });
+          env.addRequestExpectation(API_NEW_LOGIN, {
+            auth: "another_token",
+            request: {
+              scope: "write",
+              duration: {
+                "d_us": "forever",
+              },
+              refreshable: true,
+            },
+            
+          });
+
+          management.setNewAccessToken(undefined,"another_token" as 
AccessToken);
+        },
+        ({ instance, management, admin }) => {
+          expect(env.assertJustExpectedRequestWereMade()).deep.eq({
+            result: "ok",
+          });
+
+          env.addRequestExpectation(API_CREATE_INSTANCE, {
+            // auth: "another_token",
+            request: {
+              id: "new_instance_id",
+            } as MerchantBackend.Instances.InstanceConfigurationMessage,
+          });
+
+          admin.createInstance({
+            id: "new_instance_id",
+          } as MerchantBackend.Instances.InstanceConfigurationMessage);
+        },
+      ],
+      env.buildTestingContext(),
+    );
+
+    expect(hookBehavior).deep.eq({ result: "ok" });
+    expect(env.assertJustExpectedRequestWereMade()).deep.eq({ result: "ok" });
+  });
+
+  it("should use new token after updating the instance token in the settings 
as admin", async () => {
+    const env = new ApiMockEnvironment();
+
+    const hookBehavior = await tests.hookBehaveLikeThis(
+      () => {
+        const instance = useInstanceAPI();
+        const management = useManagementAPI("default");
+        const admin = useAdminAPI();
+
+        return { instance, management, admin };
+      },
+      {},
+      [
+        ({ instance, management, admin }) => {
+          env.addRequestExpectation(API_UPDATE_CURRENT_INSTANCE_AUTH, {
+            request: {
+              method: "token",
+              token: "another_token",
+            },
+            response: {
+              name: "instance_name",
+            } as MerchantBackend.Instances.QueryInstancesResponse,
+          });
+          env.addRequestExpectation(API_NEW_LOGIN, {
+            auth: "another_token",
+            request: {
+              scope: "write",
+              duration: {
+                "d_us": "forever",
+              },
+              refreshable: true,
+            },            
+          });
+          instance.setNewAccessToken(undefined, "another_token" as 
AccessToken);
+        },
+        ({ instance, management, admin }) => {
+          expect(env.assertJustExpectedRequestWereMade()).deep.eq({
+            result: "ok",
+          });
+
+          env.addRequestExpectation(API_CREATE_INSTANCE, {
+            // auth: "another_token",
+            request: {
+              id: "new_instance_id",
+            } as MerchantBackend.Instances.InstanceConfigurationMessage,
+          });
+
+          admin.createInstance({
+            id: "new_instance_id",
+          } as MerchantBackend.Instances.InstanceConfigurationMessage);
+        },
+      ],
+      env.buildTestingContext(),
+    );
+
+    expect(hookBehavior).deep.eq({ result: "ok" });
+    expect(env.assertJustExpectedRequestWereMade()).deep.eq({ result: "ok" });
+  });
+});
diff --git a/packages/auditor-backoffice-ui/src/context/backend.ts 
b/packages/auditor-backoffice-ui/src/context/backend.ts
new file mode 100644
index 000000000..2dad11f6b
--- /dev/null
+++ b/packages/auditor-backoffice-ui/src/context/backend.ts
@@ -0,0 +1,69 @@
+/*
+ This file is part of GNU Taler
+ (C) 2021-2024 Taler Systems S.A.
+
+ GNU Taler is free software; you can redistribute it and/or modify it under the
+ terms of the GNU General Public License as published by the Free Software
+ Foundation; either version 3, or (at your option) any later version.
+
+ GNU Taler is distributed in the hope that it will be useful, but WITHOUT ANY
+ WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
+ A PARTICULAR PURPOSE.  See the GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License along with
+ GNU Taler; see the file COPYING.  If not, see <http://www.gnu.org/licenses/>
+ */
+
+/**
+ *
+ * @author Sebastian Javier Marchano (sebasjm)
+ */
+
+import { useMemoryStorage } from "@gnu-taler/web-util/browser";
+import { createContext, h, VNode } from "preact";
+import { useContext } from "preact/hooks";
+import { LoginToken } from "../declaration.js";
+import { useBackendDefaultToken, useBackendURL } from "../hooks/index.js";
+
+interface BackendContextType {
+  url: string,
+  alreadyTriedLogin: boolean;
+  token?: LoginToken;
+  updateToken: (token: LoginToken | undefined) => void;
+}
+
+const BackendContext = createContext<BackendContextType>({
+  url: "",
+  alreadyTriedLogin: false,
+  token: undefined,
+  updateToken: () => null,
+});
+
+function useBackendContextState(
+  defaultUrl?: string,
+): BackendContextType {
+  const [url] = useBackendURL(defaultUrl);
+  const [token, updateToken] = useBackendDefaultToken();
+
+  return {
+    url,
+    token,
+    alreadyTriedLogin: token !== undefined,
+    updateToken,
+  };
+}
+
+export const BackendContextProvider = ({
+  children,
+  defaultUrl,
+}: {
+  children: any;
+  defaultUrl?: string;
+}): VNode => {
+  const value = useBackendContextState(defaultUrl);
+
+  return h(BackendContext.Provider, { value, children });
+};
+
+export const useBackendContext = (): BackendContextType =>
+  useContext(BackendContext);
diff --git a/packages/auditor-backoffice-ui/src/context/config.ts 
b/packages/auditor-backoffice-ui/src/context/config.ts
new file mode 100644
index 000000000..def45ea64
--- /dev/null
+++ b/packages/auditor-backoffice-ui/src/context/config.ts
@@ -0,0 +1,32 @@
+/*
+ This file is part of GNU Taler
+ (C) 2021-2024 Taler Systems S.A.
+
+ GNU Taler is free software; you can redistribute it and/or modify it under the
+ terms of the GNU General Public License as published by the Free Software
+ Foundation; either version 3, or (at your option) any later version.
+
+ GNU Taler is distributed in the hope that it will be useful, but WITHOUT ANY
+ WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
+ A PARTICULAR PURPOSE.  See the GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License along with
+ GNU Taler; see the file COPYING.  If not, see <http://www.gnu.org/licenses/>
+ */
+
+/**
+ *
+ * @author Sebastian Javier Marchano (sebasjm)
+ */
+
+import { createContext } from "preact";
+import { useContext } from "preact/hooks";
+
+interface Type {
+  currency: string;
+  version: string;
+}
+const Context = createContext<Type>(null!);
+
+export const ConfigContextProvider = Context.Provider;
+export const useConfigContext = (): Type => useContext(Context);
diff --git a/packages/auditor-backoffice-ui/src/context/instance.ts 
b/packages/auditor-backoffice-ui/src/context/instance.ts
new file mode 100644
index 000000000..5800ade7e
--- /dev/null
+++ b/packages/auditor-backoffice-ui/src/context/instance.ts
@@ -0,0 +1,36 @@
+/*
+ This file is part of GNU Taler
+ (C) 2021-2024 Taler Systems S.A.
+
+ GNU Taler is free software; you can redistribute it and/or modify it under the
+ terms of the GNU General Public License as published by the Free Software
+ Foundation; either version 3, or (at your option) any later version.
+
+ GNU Taler is distributed in the hope that it will be useful, but WITHOUT ANY
+ WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
+ A PARTICULAR PURPOSE.  See the GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License along with
+ GNU Taler; see the file COPYING.  If not, see <http://www.gnu.org/licenses/>
+ */
+
+/**
+ *
+ * @author Sebastian Javier Marchano (sebasjm)
+ */
+
+import { createContext } from "preact";
+import { useContext } from "preact/hooks";
+import { LoginToken } from "../declaration.js";
+
+interface Type {
+  id: string;
+  token?: LoginToken;
+  admin?: boolean;
+  changeToken: (t?: LoginToken) => void;
+}
+
+const Context = createContext<Type>({} as any);
+
+export const InstanceContextProvider = Context.Provider;
+export const useInstanceContext = (): Type => useContext(Context);
diff --git a/packages/auditor-backoffice-ui/src/custom.d.ts 
b/packages/auditor-backoffice-ui/src/custom.d.ts
new file mode 100644
index 000000000..34522a2dd
--- /dev/null
+++ b/packages/auditor-backoffice-ui/src/custom.d.ts
@@ -0,0 +1,42 @@
+/*
+ This file is part of GNU Taler
+ (C) 2021-2024 Taler Systems S.A.
+
+ GNU Taler is free software; you can redistribute it and/or modify it under the
+ terms of the GNU General Public License as published by the Free Software
+ Foundation; either version 3, or (at your option) any later version.
+
+ GNU Taler is distributed in the hope that it will be useful, but WITHOUT ANY
+ WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
+ A PARTICULAR PURPOSE.  See the GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License along with
+ GNU Taler; see the file COPYING.  If not, see <http://www.gnu.org/licenses/>
+ */
+declare module "*.po" {
+  const content: any;
+  export default content;
+}
+declare module "jed" {
+  const x: any;
+  export = x;
+}
+declare module "*.jpeg" {
+  const content: any;
+  export default content;
+}
+declare module "*.png" {
+  const content: any;
+  export default content;
+}
+declare module "*.svg" {
+  const content: any;
+  export default content;
+}
+
+declare module "*.scss" {
+  const content: Record<string, string>;
+  export default content;
+}
+declare const __VERSION__: string;
+declare const __GIT_HASH__: string;
diff --git a/packages/auditor-backoffice-ui/src/declaration.d.ts 
b/packages/auditor-backoffice-ui/src/declaration.d.ts
new file mode 100644
index 000000000..f0c79268c
--- /dev/null
+++ b/packages/auditor-backoffice-ui/src/declaration.d.ts
@@ -0,0 +1,1830 @@
+/*
+ This file is part of GNU Taler
+ (C) 2021-2024 Taler Systems S.A.
+
+ GNU Taler is free software; you can redistribute it and/or modify it under the
+ terms of the GNU General Public License as published by the Free Software
+ Foundation; either version 3, or (at your option) any later version.
+
+ GNU Taler is distributed in the hope that it will be useful, but WITHOUT ANY
+ WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
+ A PARTICULAR PURPOSE.  See the GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License along with
+ GNU Taler; see the file COPYING.  If not, see <http://www.gnu.org/licenses/>
+ */
+
+/**
+ *
+ * @author Sebastian Javier Marchano (sebasjm)
+ */
+
+type HashCode = string;
+type EddsaPublicKey = string;
+type EddsaSignature = string;
+type WireTransferIdentifierRawP = string;
+type RelativeTime = TalerProtocolDuration;
+type ImageDataUrl = string;
+type MerchantUserType = "business" | "individual";
+
+
+export interface WithId {
+  id: string;
+}
+
+interface Timestamp {
+  // Milliseconds since epoch, or the special
+  // value "forever" to represent an event that will
+  // never happen.
+  t_s: number | "never";
+}
+interface TalerProtocolDuration {
+  d_us: number | "forever";
+}
+interface Duration {
+  d_ms: number | "forever";
+}
+
+interface WithId {
+  id: string;
+}
+
+type Amount = string;
+type UUID = string;
+type Integer = number;
+
+interface WireAccount {
+  // payto:// URI identifying the account and wire method
+  payto_uri: string;
+
+  // URI to convert amounts from or to the currency used by
+  // this wire account of the exchange. Missing if no
+  // conversion is applicable.
+  conversion_url?: string;
+
+  // Restrictions that apply to bank accounts that would send
+  // funds to the exchange (crediting this exchange bank account).
+  // Optional, empty array for unrestricted.
+  credit_restrictions: AccountRestriction[];
+
+  // Restrictions that apply to bank accounts that would receive
+  // funds from the exchange (debiting this exchange bank account).
+  // Optional, empty array for unrestricted.
+  debit_restrictions: AccountRestriction[];
+
+  // Signature using the exchange's offline key over
+  // a TALER_MasterWireDetailsPS
+  // with purpose TALER_SIGNATURE_MASTER_WIRE_DETAILS.
+  master_sig: EddsaSignature;
+}
+
+type AccountRestriction = RegexAccountRestriction | DenyAllAccountRestriction;
+
+// Account restriction that disables this type of
+// account for the indicated operation categorically.
+interface DenyAllAccountRestriction {
+  type: "deny";
+}
+
+// Accounts interacting with this type of account
+// restriction must have a payto://-URI matching
+// the given regex.
+interface RegexAccountRestriction {
+  type: "regex";
+
+  // Regular expression that the payto://-URI of the
+  // partner account must follow.  The regular expression
+  // should follow posix-egrep, but without support for character
+  // classes, GNU extensions, back-references or intervals. See
+  // 
https://www.gnu.org/software/findutils/manual/html_node/find_html/posix_002degrep-regular-expression-syntax.html
+  // for a description of the posix-egrep syntax. Applications
+  // may support regexes with additional features, but exchanges
+  // must not use such regexes.
+  payto_regex: string;
+
+  // Hint for a human to understand the restriction
+  // (that is hopefully easier to comprehend than the regex itself).
+  human_hint: string;
+
+  // Map from IETF BCP 47 language tags to localized
+  // human hints.
+  human_hint_i18n?: { [lang_tag: string]: string };
+}
+interface LoginToken {
+  token: string,
+  expiration: Timestamp,
+}
+// token used to get loginToken
+// must forget after used
+declare const __ac_token: unique symbol;
+type AccessToken = string & {
+  [__ac_token]: true;
+};
+
+export namespace ExchangeBackend {
+  interface WireResponse {
+    // Master public key of the exchange, must match the key returned in /keys.
+    master_public_key: EddsaPublicKey;
+
+    // Array of wire accounts operated by the exchange for
+    // incoming wire transfers.
+    accounts: WireAccount[];
+
+    // Object mapping names of wire methods (i.e. "sepa" or "x-taler-bank")
+    // to wire fees.
+    fees: { method: AggregateTransferFee };
+  }
+  interface AggregateTransferFee {
+    // Per transfer wire transfer fee.
+    wire_fee: Amount;
+
+    // Per transfer closing fee.
+    closing_fee: Amount;
+
+    // What date (inclusive) does this fee go into effect?
+    // The different fees must cover the full time period in which
+    // any of the denomination keys are valid without overlap.
+    start_date: Timestamp;
+
+    // What date (exclusive) does this fee stop going into effect?
+    // The different fees must cover the full time period in which
+    // any of the denomination keys are valid without overlap.
+    end_date: Timestamp;
+
+    // Signature of TALER_MasterWireFeePS with
+    // purpose TALER_SIGNATURE_MASTER_WIRE_FEES.
+    sig: EddsaSignature;
+  }
+}
+export namespace AuditorBackend {
+  interface ErrorDetail {
+    // Numeric error code unique to the condition.
+    // The other arguments are specific to the error value reported here.
+    code: number;
+
+    // Human-readable description of the error, i.e. "missing parameter", 
"commitment violation", ...
+    // Should give a human-readable hint about the error's nature. Optional, 
may change without notice!
+    hint?: string;
+
+    // Optional detail about the specific input value that failed. May change 
without notice!
+    detail?: string;
+
+    // Name of the parameter that was bogus (if applicable).
+    parameter?: string;
+
+    // Path to the argument that was bogus (if applicable).
+    path?: string;
+
+    // Offset of the argument that was bogus (if applicable).
+    offset?: string;
+
+    // Index of the argument that was bogus (if applicable).
+    index?: string;
+
+    // Name of the object that was bogus (if applicable).
+    object?: string;
+
+    // Name of the currency than was problematic (if applicable).
+    currency?: string;
+
+    // Expected type (if applicable).
+    type_expected?: string;
+
+    // Type that was provided instead (if applicable).
+    type_actual?: string;
+  }
+  interface Exchange {
+    // the exchange's base URL
+    url: string;
+
+    // master public key of the exchange
+    master_pub: EddsaPublicKey;
+  }
+  namespace DepositConfirmation {
+    // POST /deposit-confirmation
+    interface ProductAddDetail {
+      // product ID to use.
+      product_id: string;
+
+      // Human-readable product description.
+      description: string;
+
+      // Map from IETF BCP 47 language tags to localized descriptions
+      description_i18n: { [lang_tag: string]: string };
+
+      // unit in which the product is measured (liters, kilograms, packages, 
etc.)
+      unit: string;
+
+      // The price for one unit of the product. Zero is used
+      // to imply that this product is not sold separately, or
+      // that the price is not fixed, and must be supplied by the
+      // front-end.  If non-zero, this price MUST include applicable
+      // taxes.
+      price: Amount;
+
+      // An optional base64-encoded product image
+      image: ImageDataUrl;
+
+      // a list of taxes paid by the merchant for one unit of this product
+      taxes: Tax[];
+
+      // Number of units of the product in stock in sum in total,
+      // including all existing sales ever. Given in product-specific
+      // units.
+      // A value of -1 indicates "infinite" (i.e. for "electronic" books).
+      total_stock: Integer;
+
+      // Identifies where the product is in stock.
+      address: Location;
+
+      // Identifies when we expect the next restocking to happen.
+      next_restock?: Timestamp;
+
+      // Minimum age buyer must have (in years). Default is 0.
+      minimum_age?: Integer;
+    }
+    //   PATCH /private/products/$PRODUCT_ID
+    interface ProductPatchDetail {
+      // Human-readable product description.
+      description: string;
+
+      // Map from IETF BCP 47 language tags to localized descriptions
+      description_i18n: { [lang_tag: string]: string };
+
+      // unit in which the product is measured (liters, kilograms, packages, 
etc.)
+      unit: string;
+
+      // The price for one unit of the product. Zero is used
+      // to imply that this product is not sold separately, or
+      // that the price is not fixed, and must be supplied by the
+      // front-end.  If non-zero, this price MUST include applicable
+      // taxes.
+      price: Amount;
+
+      // An optional base64-encoded product image
+      image: ImageDataUrl;
+
+      // a list of taxes paid by the merchant for one unit of this product
+      taxes: Tax[];
+
+      // Number of units of the product in stock in sum in total,
+      // including all existing sales ever. Given in product-specific
+      // units.
+      // A value of -1 indicates "infinite" (i.e. for "electronic" books).
+      total_stock: Integer;
+
+      // Number of units of the product that were lost (spoiled, stolen, etc.)
+      total_lost: Integer;
+
+      // Identifies where the product is in stock.
+      address: Location;
+
+      // Identifies when we expect the next restocking to happen.
+      next_restock?: Timestamp;
+
+      // Minimum age buyer must have (in years). Default is 0.
+      minimum_age?: Integer;
+    }
+
+    // GET /deposit-confirmation
+    interface DepositConfirmationList  {
+      depositConfirmations: DepositConfirmation [];
+    }
+    interface DepositConfirmation  {
+      serial_id: string;
+      timestamp: string;
+      refund_deadline: string;
+      wire_deadline: string;
+      amount_without_fee: string;
+    }
+
+    // GET /private/products/$PRODUCT_ID
+    interface DepositConfirmationDetail {
+      // Human-readable product description.
+      description: string;
+
+      // Map from IETF BCP 47 language tags to localized descriptions
+      description_i18n: { [lang_tag: string]: string };
+
+      // unit in which the product is measured (liters, kilograms, packages, 
etc.)
+      unit: string;
+
+      // The price for one unit of the product. Zero is used
+      // to imply that this product is not sold separately, or
+      // that the price is not fixed, and must be supplied by the
+      // front-end.  If non-zero, this price MUST include applicable
+      // taxes.
+      price: Amount;
+
+      // An optional base64-encoded product image
+      image: ImageDataUrl;
+
+      // a list of taxes paid by the merchant for one unit of this product
+      taxes: Tax[];
+
+      // Number of units of the product in stock in sum in total,
+      // including all existing sales ever. Given in product-specific
+      // units.
+      // A value of -1 indicates "infinite" (i.e. for "electronic" books).
+      total_stock: Integer;
+
+      // Number of units of the product that have already been sold.
+      total_sold: Integer;
+
+      // Number of units of the product that were lost (spoiled, stolen, etc.)
+      total_lost: Integer;
+
+      // Identifies where the product is in stock.
+      address: Location;
+
+      // Identifies when we expect the next restocking to happen.
+      next_restock?: Timestamp;
+
+      // Minimum age buyer must have (in years). Default is 0.
+      minimum_age?: Integer;
+    }
+  }
+
+}
+export namespace MerchantBackend {
+  interface ErrorDetail {
+    // Numeric error code unique to the condition.
+    // The other arguments are specific to the error value reported here.
+    code: number;
+
+    // Human-readable description of the error, i.e. "missing parameter", 
"commitment violation", ...
+    // Should give a human-readable hint about the error's nature. Optional, 
may change without notice!
+    hint?: string;
+
+    // Optional detail about the specific input value that failed. May change 
without notice!
+    detail?: string;
+
+    // Name of the parameter that was bogus (if applicable).
+    parameter?: string;
+
+    // Path to the argument that was bogus (if applicable).
+    path?: string;
+
+    // Offset of the argument that was bogus (if applicable).
+    offset?: string;
+
+    // Index of the argument that was bogus (if applicable).
+    index?: string;
+
+    // Name of the object that was bogus (if applicable).
+    object?: string;
+
+    // Name of the currency than was problematic (if applicable).
+    currency?: string;
+
+    // Expected type (if applicable).
+    type_expected?: string;
+
+    // Type that was provided instead (if applicable).
+    type_actual?: string;
+  }
+
+  // Delivery location, loosely modeled as a subset of
+  // ISO20022's PostalAddress25.
+  interface Tax {
+    // the name of the tax
+    name: string;
+
+    // amount paid in tax
+    tax: Amount;
+  }
+
+  interface Auditor {
+    // official name
+    name: string;
+
+    // Auditor's public key
+    auditor_pub: EddsaPublicKey;
+
+    // Base URL of the auditor
+    url: string;
+  }
+  interface Exchange {
+    // the exchange's base URL
+    url: string;
+
+    // master public key of the exchange
+    master_pub: EddsaPublicKey;
+  }
+
+  interface Product {
+    // merchant-internal identifier for the product.
+    product_id?: string;
+
+    // Human-readable product description.
+    description: string;
+
+    // Map from IETF BCP 47 language tags to localized descriptions
+    description_i18n?: { [lang_tag: string]: string };
+
+    // The number of units of the product to deliver to the customer.
+    quantity: Integer;
+
+    // The unit in which the product is measured (liters, kilograms, packages, 
etc.)
+    unit: string;
+
+    // The price of the product; this is the total price for quantity times 
unit of this product.
+    price?: Amount;
+
+    // An optional base64-encoded product image
+    image: ImageDataUrl;
+
+    // a list of taxes paid by the merchant for this product. Can be empty.
+    taxes: Tax[];
+
+    // time indicating when this product should be delivered
+    delivery_date?: TalerProtocolTimestamp;
+
+    // Minimum age buyer must have (in years). Default is 0.
+    minimum_age?: Integer;
+  }
+  interface Merchant {
+    // label for a location with the business address of the merchant
+    address: Location;
+
+    // the merchant's legal name of business
+    name: string;
+
+    // label for a location that denotes the jurisdiction for disputes.
+    // Some of the typical fields for a location (such as a street address) 
may be absent.
+    jurisdiction: Location;
+  }
+
+  interface VersionResponse {
+    // libtool-style representation of the Merchant protocol version, see
+    // 
https://www.gnu.org/software/libtool/manual/html_node/Versioning.html#Versioning
+    // The format is "current:revision:age".
+    version: string;
+
+    // Name of the protocol.
+    name: "taler-merchant";
+
+    // Currency supported by this backend.
+    currency: string;
+  }
+  interface Location {
+    // Nation with its own government.
+    country?: string;
+
+    // Identifies a subdivision of a country such as state, region, county.
+    country_subdivision?: string;
+
+    // Identifies a subdivision within a country sub-division.
+    district?: string;
+
+    // Name of a built-up area, with defined boundaries, and a local 
government.
+    town?: string;
+
+    // Specific location name within the town.
+    town_location?: string;
+
+    // Identifier consisting of a group of letters and/or numbers that
+    // is added to a postal address to assist the sorting of mail.
+    post_code?: string;
+
+    // Name of a street or thoroughfare.
+    street?: string;
+
+    // Name of the building or house.
+    building_name?: string;
+
+    // Number that identifies the position of a building on a street.
+    building_number?: string;
+
+    // Free-form address lines, should not exceed 7 elements.
+    address_lines?: string[];
+  }
+  namespace Instances {
+    //POST /private/instances/$INSTANCE/auth
+    interface InstanceAuthConfigurationMessage {
+      // Type of authentication.
+      // "external":  The mechant backend does not do
+      //   any authentication checks.  Instead an API
+      //   gateway must do the authentication.
+      // "token": The merchant checks an auth token.
+      //   See "token" for details.
+      method: "external" | "token";
+
+      // For method "external", this field is mandatory.
+      // The token MUST begin with the string "secret-token:".
+      // After the auth token has been set (with method "token"),
+      // the value must be provided in a "Authorization: Bearer $token"
+      // header.
+      token?: string;
+    }
+    //POST /private/instances
+    interface InstanceConfigurationMessage {
+      // Name of the merchant instance to create (will become $INSTANCE).
+      id: string;
+
+      // Merchant name corresponding to this instance.
+      name: string;
+
+      // Type of the user (business or individual).
+      // Defaults to 'business'. Should become mandatory field
+      // in the future, left as optional for API compatibility for now.
+      user_type?: MerchantUserType;
+
+      // Merchant email for customer contact.
+      email?: string;
+
+      // Merchant public website.
+      website?: string;
+
+      // Merchant logo.
+      logo?: ImageDataUrl;
+
+      // "Authentication" header required to authorize management access the 
instance.
+      // Optional, if not given authentication will be disabled for
+      // this instance (hopefully authentication checks are still
+      // done by some reverse proxy).
+      auth: InstanceAuthConfigurationMessage;
+
+      // The merchant's physical address (to be put into contracts).
+      address: Location;
+
+      // The jurisdiction under which the merchant conducts its business
+      // (to be put into contracts).
+      jurisdiction: Location;
+
+      // Use STEFAN curves to determine default fees?
+      // If false, no fees are allowed by default.
+      // Can always be overridden by the frontend on a per-order basis.
+      use_stefan: boolean;
+
+      //  If the frontend does NOT specify an execution date, how long should
+      // we tell the exchange to wait to aggregate transactions before
+      // executing the wire transfer?  This delay is added to the current
+      // time when we generate the advisory execution time for the exchange.
+      default_wire_transfer_delay: RelativeTime;
+
+      // If the frontend does NOT specify a payment deadline, how long should
+      // offers we make be valid by default?
+      default_pay_delay: RelativeTime;
+    }
+
+    // PATCH /private/instances/$INSTANCE
+    interface InstanceReconfigurationMessage {
+
+      // Merchant name corresponding to this instance.
+      name: string;
+
+      // Type of the user (business or individual).
+      // Defaults to 'business'. Should become mandatory field
+      // in the future, left as optional for API compatibility for now.
+      user_type?: MerchantUserType;
+
+      // Merchant email for customer contact.
+      email?: string;
+
+      // Merchant public website.
+      website?: string;
+
+      // Merchant logo.
+      logo?: ImageDataUrl;
+
+      // The merchant's physical address (to be put into contracts).
+      address: Location;
+
+      // The jurisdiction under which the merchant conducts its business
+      // (to be put into contracts).
+      jurisdiction: Location;
+
+      // Use STEFAN curves to determine default fees?
+      // If false, no fees are allowed by default.
+      // Can always be overridden by the frontend on a per-order basis.
+      use_stefan: boolean;
+
+      //  If the frontend does NOT specify an execution date, how long should
+      // we tell the exchange to wait to aggregate transactions before
+      // executing the wire transfer?  This delay is added to the current
+      // time when we generate the advisory execution time for the exchange.
+      default_wire_transfer_delay: RelativeTime;
+
+      // If the frontend does NOT specify a payment deadline, how long should
+      // offers we make be valid by default?
+      default_pay_delay: RelativeTime;
+    }
+
+    //   GET /private/instances
+    interface InstancesResponse {
+      // List of instances that are present in the backend (see Instance)
+      instances: Instance[];
+    }
+
+    interface Instance {
+      // Merchant name corresponding to this instance.
+      name: string;
+
+      // Type of the user ("business" or "individual").
+      user_type: MerchantUserType;
+
+      // Merchant public website.
+      website?: string;
+
+      // Merchant logo.
+      logo?: ImageDataUrl;
+
+      // Merchant instance this response is about ($INSTANCE)
+      id: string;
+
+      // Public key of the merchant/instance, in Crockford Base32 encoding.
+      merchant_pub: EddsaPublicKey;
+
+      // List of the payment targets supported by this instance. Clients can
+      // specify the desired payment target in /order requests.  Note that
+      // front-ends do not have to support wallets selecting payment targets.
+      payment_targets: string[];
+
+      // Has this instance been deleted (but not purged)?
+      deleted: boolean;
+    }
+
+    //GET /private/instances/$INSTANCE
+    interface QueryInstancesResponse {
+
+      // Merchant name corresponding to this instance.
+      name: string;
+      // Type of the user ("business" or "individual").
+      user_type: MerchantUserType;
+
+      // Merchant email for customer contact.
+      email?: string;
+
+      // Merchant public website.
+      website?: string;
+
+      // Merchant logo.
+      logo?: ImageDataUrl;
+
+      // Public key of the merchant/instance, in Crockford Base32 encoding.
+      merchant_pub: EddsaPublicKey;
+
+      // The merchant's physical address (to be put into contracts).
+      address: Location;
+
+      // The jurisdiction under which the merchant conducts its business
+      // (to be put into contracts).
+      jurisdiction: Location;
+
+      // Use STEFAN curves to determine default fees?
+      // If false, no fees are allowed by default.
+      // Can always be overridden by the frontend on a per-order basis.
+      use_stefan: boolean;
+
+      //  If the frontend does NOT specify an execution date, how long should
+      // we tell the exchange to wait to aggregate transactions before
+      // executing the wire transfer?  This delay is added to the current
+      // time when we generate the advisory execution time for the exchange.
+      default_wire_transfer_delay: RelativeTime;
+
+      // If the frontend does NOT specify a payment deadline, how long should
+      // offers we make be valid by default?
+      default_pay_delay: RelativeTime;
+
+      // Authentication configuration.
+      // Does not contain the token when token auth is configured.
+      auth: {
+        method: "external" | "token";
+      };
+    }
+    //   DELETE /private/instances/$INSTANCE
+    interface LoginTokenRequest {
+      // Scope of the token (which kinds of operations it will allow)
+      scope: "readonly" | "write";
+
+      // Server may impose its own upper bound
+      // on the token validity duration
+      duration?: RelativeTime;
+
+      // Can this token be refreshed?
+      // Defaults to false.
+      refreshable?: boolean;
+    }
+    interface LoginTokenSuccessResponse {
+      // The login token that can be used to access resources
+      // that are in scope for some time. Must be prefixed
+      // with "Bearer " when used in the "Authorization" HTTP header.
+      // Will already begin with the RFC 8959 prefix.
+      token: string;
+
+      // Scope of the token (which kinds of operations it will allow)
+      scope: "readonly" | "write";
+
+      // Server may impose its own upper bound
+      // on the token validity duration
+      expiration: Timestamp;
+
+      // Can this token be refreshed?
+      refreshable: boolean;
+    }
+  }
+
+  namespace KYC {
+    //GET /private/instances/$INSTANCE/kyc
+    interface AccountKycRedirects {
+      // Array of pending KYCs.
+      pending_kycs: MerchantAccountKycRedirect[];
+
+      // Array of exchanges with no reply.
+      timeout_kycs: ExchangeKycTimeout[];
+    }
+    interface MerchantAccountKycRedirect {
+      // URL that the user should open in a browser to
+      // proceed with the KYC process (as returned
+      // by the exchange's /kyc-check/ endpoint).
+      // Optional, missing if the account is blocked
+      // due to AML and not due to KYC.
+      kyc_url?: string;
+
+      // Base URL of the exchange this is about.
+      exchange_url: string;
+
+      // AML status of the account.
+      aml_status: number;
+
+      // Our bank wire account this is about.
+      payto_uri: string;
+    }
+    interface ExchangeKycTimeout {
+      // Base URL of the exchange this is about.
+      exchange_url: string;
+
+      // Numeric error code indicating errors the exchange
+      // returned, or TALER_EC_INVALID for none.
+      exchange_code: number;
+
+      // HTTP status code returned by the exchange when we asked for
+      // information about the KYC status.
+      // 0 if there was no response at all.
+      exchange_http_status: number;
+    }
+
+  }
+
+  namespace BankAccounts {
+
+    interface AccountAddDetails {
+
+      // payto:// URI of the account.
+      payto_uri: string;
+
+      // URL from where the merchant can download information
+      // about incoming wire transfers to this account.
+      credit_facade_url?: string;
+
+      // Credentials to use when accessing the credit facade.
+      // Never returned on a GET (as this may be somewhat
+      // sensitive data). Can be set in POST
+      // or PATCH requests to update (or delete) credentials.
+      // To really delete credentials, set them to the type: "none".
+      credit_facade_credentials?: FacadeCredentials;
+
+    }
+
+    type FacadeCredentials =
+      | NoFacadeCredentials
+      | BasicAuthFacadeCredentials;
+
+    interface NoFacadeCredentials {
+      type: "none";
+    }
+
+    interface BasicAuthFacadeCredentials {
+      type: "basic";
+
+      // Username to use to authenticate
+      username: string;
+
+      // Password to use to authenticate
+      password: string;
+    }
+
+    interface AccountAddResponse {
+      // Hash over the wire details (including over the salt).
+      h_wire: HashCode;
+
+      // Salt used to compute h_wire.
+      salt: HashCode;
+    }
+
+    interface AccountPatchDetails {
+
+      // URL from where the merchant can download information
+      // about incoming wire transfers to this account.
+      credit_facade_url?: string;
+
+      // Credentials to use when accessing the credit facade.
+      // Never returned on a GET (as this may be somewhat
+      // sensitive data). Can be set in POST
+      // or PATCH requests to update (or delete) credentials.
+      // To really delete credentials, set them to the type: "none".
+      credit_facade_credentials?: FacadeCredentials;
+    }
+
+
+    interface AccountsSummaryResponse {
+
+      // List of accounts that are known for the instance.
+      accounts: BankAccountEntry[];
+    }
+
+    interface BankAccountEntry {
+      // payto:// URI of the account.
+      payto_uri: string;
+
+      // Hash over the wire details (including over the salt)
+      h_wire: HashCode;
+
+      // salt used to compute h_wire
+      salt: HashCode;
+
+      // URL from where the merchant can download information
+      // about incoming wire transfers to this account.
+      credit_facade_url?: string;
+
+      // Credentials to use when accessing the credit facade.
+      // Never returned on a GET (as this may be somewhat
+      // sensitive data). Can be set in POST
+      // or PATCH requests to update (or delete) credentials.
+      credit_facade_credentials?: FacadeCredentials;
+
+      // true if this account is active,
+      // false if it is historic.
+      active: boolean;
+    }
+
+  }
+
+  namespace Products {
+    // POST /private/products
+    interface ProductAddDetail {
+      // product ID to use.
+      product_id: string;
+
+      // Human-readable product description.
+      description: string;
+
+      // Map from IETF BCP 47 language tags to localized descriptions
+      description_i18n: { [lang_tag: string]: string };
+
+      // unit in which the product is measured (liters, kilograms, packages, 
etc.)
+      unit: string;
+
+      // The price for one unit of the product. Zero is used
+      // to imply that this product is not sold separately, or
+      // that the price is not fixed, and must be supplied by the
+      // front-end.  If non-zero, this price MUST include applicable
+      // taxes.
+      price: Amount;
+
+      // An optional base64-encoded product image
+      image: ImageDataUrl;
+
+      // a list of taxes paid by the merchant for one unit of this product
+      taxes: Tax[];
+
+      // Number of units of the product in stock in sum in total,
+      // including all existing sales ever. Given in product-specific
+      // units.
+      // A value of -1 indicates "infinite" (i.e. for "electronic" books).
+      total_stock: Integer;
+
+      // Identifies where the product is in stock.
+      address: Location;
+
+      // Identifies when we expect the next restocking to happen.
+      next_restock?: Timestamp;
+
+      // Minimum age buyer must have (in years). Default is 0.
+      minimum_age?: Integer;
+    }
+    //   PATCH /private/products/$PRODUCT_ID
+    interface ProductPatchDetail {
+      // Human-readable product description.
+      description: string;
+
+      // Map from IETF BCP 47 language tags to localized descriptions
+      description_i18n: { [lang_tag: string]: string };
+
+      // unit in which the product is measured (liters, kilograms, packages, 
etc.)
+      unit: string;
+
+      // The price for one unit of the product. Zero is used
+      // to imply that this product is not sold separately, or
+      // that the price is not fixed, and must be supplied by the
+      // front-end.  If non-zero, this price MUST include applicable
+      // taxes.
+      price: Amount;
+
+      // An optional base64-encoded product image
+      image: ImageDataUrl;
+
+      // a list of taxes paid by the merchant for one unit of this product
+      taxes: Tax[];
+
+      // Number of units of the product in stock in sum in total,
+      // including all existing sales ever. Given in product-specific
+      // units.
+      // A value of -1 indicates "infinite" (i.e. for "electronic" books).
+      total_stock: Integer;
+
+      // Number of units of the product that were lost (spoiled, stolen, etc.)
+      total_lost: Integer;
+
+      // Identifies where the product is in stock.
+      address: Location;
+
+      // Identifies when we expect the next restocking to happen.
+      next_restock?: Timestamp;
+
+      // Minimum age buyer must have (in years). Default is 0.
+      minimum_age?: Integer;
+    }
+
+    // GET /private/products
+    interface InventorySummaryResponse {
+      // List of products that are present in the inventory
+      products: InventoryEntry[];
+    }
+    interface InventoryEntry {
+      // Product identifier, as found in the product.
+      product_id: string;
+    }
+
+    // GET /private/products/$PRODUCT_ID
+    interface ProductDetail {
+      // Human-readable product description.
+      description: string;
+
+      // Map from IETF BCP 47 language tags to localized descriptions
+      description_i18n: { [lang_tag: string]: string };
+
+      // unit in which the product is measured (liters, kilograms, packages, 
etc.)
+      unit: string;
+
+      // The price for one unit of the product. Zero is used
+      // to imply that this product is not sold separately, or
+      // that the price is not fixed, and must be supplied by the
+      // front-end.  If non-zero, this price MUST include applicable
+      // taxes.
+      price: Amount;
+
+      // An optional base64-encoded product image
+      image: ImageDataUrl;
+
+      // a list of taxes paid by the merchant for one unit of this product
+      taxes: Tax[];
+
+      // Number of units of the product in stock in sum in total,
+      // including all existing sales ever. Given in product-specific
+      // units.
+      // A value of -1 indicates "infinite" (i.e. for "electronic" books).
+      total_stock: Integer;
+
+      // Number of units of the product that have already been sold.
+      total_sold: Integer;
+
+      // Number of units of the product that were lost (spoiled, stolen, etc.)
+      total_lost: Integer;
+
+      // Identifies where the product is in stock.
+      address: Location;
+
+      // Identifies when we expect the next restocking to happen.
+      next_restock?: Timestamp;
+
+      // Minimum age buyer must have (in years). Default is 0.
+      minimum_age?: Integer;
+    }
+
+    // POST /private/products/$PRODUCT_ID/lock
+    interface LockRequest {
+      // UUID that identifies the frontend performing the lock
+      // It is suggested that clients use a timeflake for this,
+      // see https://github.com/anthonynsimon/timeflake
+      lock_uuid: UUID;
+
+      // How long does the frontend intend to hold the lock
+      duration: RelativeTime;
+
+      // How many units should be locked?
+      quantity: Integer;
+    }
+
+    //   DELETE /private/products/$PRODUCT_ID
+  }
+
+  namespace Orders {
+    type MerchantOrderStatusResponse =
+      | CheckPaymentPaidResponse
+      | CheckPaymentClaimedResponse
+      | CheckPaymentUnpaidResponse;
+    interface CheckPaymentPaidResponse {
+      // The customer paid for this contract.
+      order_status: "paid";
+
+      // Was the payment refunded (even partially)?
+      refunded: boolean;
+
+      // True if there are any approved refunds that the wallet has
+      // not yet obtained.
+      refund_pending: boolean;
+
+      // Did the exchange wire us the funds?
+      wired: boolean;
+
+      // Total amount the exchange deposited into our bank account
+      // for this contract, excluding fees.
+      deposit_total: Amount;
+
+      // Numeric error code indicating errors the exchange
+      // encountered tracking the wire transfer for this purchase (before
+      // we even got to specific coin issues).
+      // 0 if there were no issues.
+      exchange_ec: number;
+
+      // HTTP status code returned by the exchange when we asked for
+      // information to track the wire transfer for this purchase.
+      // 0 if there were no issues.
+      exchange_hc: number;
+
+      // Total amount that was refunded, 0 if refunded is false.
+      refund_amount: Amount;
+
+      // Contract terms.
+      contract_terms: ContractTerms;
+
+      // The wire transfer status from the exchange for this order if
+      // available, otherwise empty array.
+      wire_details: TransactionWireTransfer[];
+
+      // Reports about trouble obtaining wire transfer details,
+      // empty array if no trouble were encountered.
+      wire_reports: TransactionWireReport[];
+
+      // The refund details for this order.  One entry per
+      // refunded coin; empty array if there are no refunds.
+      refund_details: RefundDetails[];
+
+      // Status URL, can be used as a redirect target for the browser
+      // to show the order QR code / trigger the wallet.
+      order_status_url: string;
+    }
+    interface CheckPaymentClaimedResponse {
+      // A wallet claimed the order, but did not yet pay for the contract.
+      order_status: "claimed";
+
+      // Contract terms.
+      contract_terms: ContractTerms;
+    }
+    interface CheckPaymentUnpaidResponse {
+      // The order was neither claimed nor paid.
+      order_status: "unpaid";
+
+      // when was the order created
+      creation_time: Timestamp;
+
+      // Order summary text.
+      summary: string;
+
+      // Total amount of the order (to be paid by the customer).
+      total_amount: Amount;
+
+      // URI that the wallet must process to complete the payment.
+      taler_pay_uri: string;
+
+      // Alternative order ID which was paid for already in the same session.
+      // Only given if the same product was purchased before in the same 
session.
+      already_paid_order_id?: string;
+
+      // Fulfillment URL of an already paid order. Only given if under this
+      // session an already paid order with a fulfillment URL exists.
+      already_paid_fulfillment_url?: string;
+
+      // Status URL, can be used as a redirect target for the browser
+      // to show the order QR code / trigger the wallet.
+      order_status_url: string;
+
+      // We do we NOT return the contract terms here because they may not
+      // exist in case the wallet did not yet claim them.
+    }
+    interface RefundDetails {
+      // Reason given for the refund.
+      reason: string;
+
+      // When was the refund approved.
+      timestamp: Timestamp;
+
+      // Set to true if a refund is still available for the wallet for this 
payment.
+      pending: boolean;
+
+      // Total amount that was refunded (minus a refund fee).
+      amount: Amount;
+    }
+    interface TransactionWireTransfer {
+      // Responsible exchange.
+      exchange_url: string;
+
+      // 32-byte wire transfer identifier.
+      wtid: Base32;
+
+      // Execution time of the wire transfer.
+      execution_time: Timestamp;
+
+      // Total amount that has been wire transferred
+      // to the merchant.
+      amount: Amount;
+
+      // Was this transfer confirmed by the merchant via the
+      // POST /transfers API, or is it merely claimed by the exchange?
+      confirmed: boolean;
+    }
+    interface TransactionWireReport {
+      // Numerical error code.
+      code: number;
+
+      // Human-readable error description.
+      hint: string;
+
+      // Numerical error code from the exchange.
+      exchange_ec: number;
+
+      // HTTP status code received from the exchange.
+      exchange_hc: number;
+
+      // Public key of the coin for which we got the exchange error.
+      coin_pub: CoinPublicKey;
+    }
+
+    interface OrderHistory {
+      // timestamp-sorted array of all orders matching the query.
+      // The order of the sorting depends on the sign of delta.
+      orders: OrderHistoryEntry[];
+    }
+    interface OrderHistoryEntry {
+      // order ID of the transaction related to this entry.
+      order_id: string;
+
+      // row ID of the order in the database
+      row_id: number;
+
+      // when the order was created
+      timestamp: Timestamp;
+
+      // the amount of money the order is for
+      amount: Amount;
+
+      // the summary of the order
+      summary: string;
+
+      // whether some part of the order is refundable,
+      // that is the refund deadline has not yet expired
+      // and the total amount refunded so far is below
+      // the value of the original transaction.
+      refundable: boolean;
+
+      // whether the order has been paid or not
+      paid: boolean;
+    }
+
+    interface PostOrderRequest {
+      // The order must at least contain the minimal
+      // order detail, but can override all
+      order: Order;
+
+      // if set, the backend will then set the refund deadline to the current
+      // time plus the specified delay.  If it's not set, refunds will not be
+      // possible.
+      refund_delay?: RelativeTime;
+
+      // specifies the payment target preferred by the client. Can be used
+      // to select among the various (active) wire methods supported by the 
instance.
+      payment_target?: string;
+
+      // specifies that some products are to be included in the
+      // order from the inventory.  For these inventory management
+      // is performed (so the products must be in stock) and
+      // details are completed from the product data of the backend.
+      inventory_products?: MinimalInventoryProduct[];
+
+      // Specifies a lock identifier that was used to
+      // lock a product in the inventory.  Only useful if
+      // manage_inventory is set.  Used in case a frontend
+      // reserved quantities of the individual products while
+      // the shopping card was being built.  Multiple UUIDs can
+      // be used in case different UUIDs were used for different
+      // products (i.e. in case the user started with multiple
+      // shopping sessions that were combined during checkout).
+      lock_uuids?: UUID[];
+
+      // Should a token for claiming the order be generated?
+      // False can make sense if the ORDER_ID is sufficiently
+      // high entropy to prevent adversarial claims (like it is
+      // if the backend auto-generates one). Default is 'true'.
+      create_token?: boolean;
+
+      // OTP device ID to associate with the order.
+      // This parameter is optional.
+      otp_id?: string;
+    }
+    type Order = MinimalOrderDetail | ContractTerms;
+
+    interface MinimalOrderDetail {
+      // Amount to be paid by the customer
+      amount: Amount;
+
+      // Short summary of the order
+      summary: string;
+
+      // URL that will show that the order was successful after
+      // it has been paid for.  Optional. When POSTing to the
+      // merchant, the placeholder "${ORDER_ID}" will be
+      // replaced with the actual order ID (useful if the
+      // order ID is generated server-side and needs to be
+      // in the URL).
+      fulfillment_url?: string;
+    }
+
+    interface MinimalInventoryProduct {
+      // Which product is requested (here mandatory!)
+      product_id: string;
+
+      // How many units of the product are requested
+      quantity: Integer;
+    }
+    interface PostOrderResponse {
+      // Order ID of the response that was just created
+      order_id: string;
+
+      // Token that authorizes the wallet to claim the order.
+      // Provided only if "create_token" was set to 'true'
+      // in the request.
+      token?: ClaimToken;
+    }
+    interface OutOfStockResponse {
+      // Product ID of an out-of-stock item
+      product_id: string;
+
+      // Requested quantity
+      requested_quantity: Integer;
+
+      // Available quantity (must be below requested_quanitity)
+      available_quantity: Integer;
+
+      // When do we expect the product to be again in stock?
+      // Optional, not given if unknown.
+      restock_expected?: Timestamp;
+    }
+
+    interface ForgetRequest {
+      // Array of valid JSON paths to forgettable fields in the order's
+      // contract terms.
+      fields: string[];
+    }
+    interface RefundRequest {
+      // Amount to be refunded
+      refund: Amount;
+
+      // Human-readable refund justification
+      reason: string;
+    }
+    interface MerchantRefundResponse {
+      // URL (handled by the backend) that the wallet should access to
+      // trigger refund processing.
+      // taler://refund/...
+      taler_refund_uri: string;
+
+      // Contract hash that a client may need to authenticate an
+      // HTTP request to obtain the above URI in a wallet-friendly way.
+      h_contract: HashCode;
+    }
+  }
+
+  namespace Rewards {
+    // GET /private/reserves
+    interface RewardReserveStatus {
+      // Array of all known reserves (possibly empty!)
+      reserves: ReserveStatusEntry[];
+    }
+    interface ReserveStatusEntry {
+      // Public key of the reserve
+      reserve_pub: EddsaPublicKey;
+
+      // Timestamp when it was established
+      creation_time: Timestamp;
+
+      // Timestamp when it expires
+      expiration_time: Timestamp;
+
+      // Initial amount as per reserve creation call
+      merchant_initial_amount: Amount;
+
+      // Initial amount as per exchange, 0 if exchange did
+      // not confirm reserve creation yet.
+      exchange_initial_amount: Amount;
+
+      // Amount picked up so far.
+      pickup_amount: Amount;
+
+      // Amount approved for rewards that exceeds the pickup_amount.
+      committed_amount: Amount;
+
+      // Is this reserve active (false if it was deleted but not purged)
+      active: boolean;
+    }
+
+    interface ReserveCreateRequest {
+      // Amount that the merchant promises to put into the reserve
+      initial_balance: Amount;
+
+      // Exchange the merchant intends to use for reward
+      exchange_url: string;
+
+      // Desired wire method, for example "iban" or "x-taler-bank"
+      wire_method: string;
+    }
+    interface ReserveCreateConfirmation {
+      // Public key identifying the reserve
+      reserve_pub: EddsaPublicKey;
+
+      // Wire accounts of the exchange where to transfer the funds.
+      accounts: WireAccount[];
+    }
+    interface RewardCreateRequest {
+      // Amount that the customer should be reward
+      amount: Amount;
+
+      // Justification for giving the reward
+      justification: string;
+
+      // URL that the user should be directed to after rewarding,
+      // will be included in the reward_token.
+      next_url: string;
+    }
+    interface RewardCreateConfirmation {
+      // Unique reward identifier for the reward that was created.
+      reward_id: HashCode;
+
+      // taler://reward URI for the reward
+      taler_reward_uri: string;
+
+      // URL that will directly trigger processing
+      // the reward when the browser is redirected to it
+      reward_status_url: string;
+
+      // when does the reward expire
+      reward_expiration: Timestamp;
+    }
+
+    interface ReserveDetail {
+      // Timestamp when it was established.
+      creation_time: Timestamp;
+
+      // Timestamp when it expires.
+      expiration_time: Timestamp;
+
+      // Initial amount as per reserve creation call.
+      merchant_initial_amount: Amount;
+
+      // Initial amount as per exchange, 0 if exchange did
+      // not confirm reserve creation yet.
+      exchange_initial_amount: Amount;
+
+      // Amount picked up so far.
+      pickup_amount: Amount;
+
+      // Amount approved for rewards that exceeds the pickup_amount.
+      committed_amount: Amount;
+
+      // Array of all rewards created by this reserves (possibly empty!).
+      // Only present if asked for explicitly.
+      rewards?: RewardStatusEntry[];
+
+      // Is this reserve active (false if it was deleted but not purged)?
+      active: boolean;
+
+      // Array of wire accounts of the exchange that could
+      // be used to fill the reserve, can be NULL
+      // if the reserve is inactive or was already filled
+      accounts?: WireAccount[];
+
+      // URL of the exchange hosting the reserve,
+      // NULL if the reserve is inactive
+      exchange_url: string;
+    }
+
+    interface RewardStatusEntry {
+      // Unique identifier for the reward.
+      reward_id: HashCode;
+
+      // Total amount of the reward that can be withdrawn.
+      total_amount: Amount;
+
+      // Human-readable reason for why the reward was granted.
+      reason: string;
+    }
+
+    interface RewardDetails {
+      // Amount that we authorized for this reward.
+      total_authorized: Amount;
+
+      // Amount that was picked up by the user already.
+      total_picked_up: Amount;
+
+      // Human-readable reason given when authorizing the reward.
+      reason: string;
+
+      // Timestamp indicating when the reward is set to expire (may be in the 
past).
+      expiration: Timestamp;
+
+      // Reserve public key from which the reward is funded.
+      reserve_pub: EddsaPublicKey;
+
+      // Array showing the pickup operations of the wallet (possibly empty!).
+      // Only present if asked for explicitly.
+      pickups?: PickupDetail[];
+    }
+    interface PickupDetail {
+      // Unique identifier for the pickup operation.
+      pickup_id: HashCode;
+
+      // Number of planchets involved.
+      num_planchets: Integer;
+
+      // Total amount requested for this pickup_id.
+      requested_amount: Amount;
+    }
+  }
+
+  namespace Transfers {
+    interface TransferList {
+      // list of all the transfers that fit the filter that we know
+      transfers: TransferDetails[];
+    }
+    interface TransferDetails {
+      // how much was wired to the merchant (minus fees)
+      credit_amount: Amount;
+
+      // raw wire transfer identifier identifying the wire transfer (a 
base32-encoded value)
+      wtid: string;
+
+      // target account that received the wire transfer
+      payto_uri: string;
+
+      // base URL of the exchange that made the wire transfer
+      exchange_url: string;
+
+      // Serial number identifying the transfer in the merchant backend.
+      // Used for filgering via offset.
+      transfer_serial_id: number;
+
+      // Time of the execution of the wire transfer by the exchange, according 
to the exchange
+      // Only provided if we did get an answer from the exchange.
+      execution_time?: Timestamp;
+
+      // True if we checked the exchange's answer and are happy with it.
+      // False if we have an answer and are unhappy, missing if we
+      // do not have an answer from the exchange.
+      verified?: boolean;
+
+      // True if the merchant uses the POST /transfers API to confirm
+      // that this wire transfer took place (and it is thus not
+      // something merely claimed by the exchange).
+      confirmed?: boolean;
+    }
+
+    interface TransferInformation {
+      // how much was wired to the merchant (minus fees)
+      credit_amount: Amount;
+
+      // raw wire transfer identifier identifying the wire transfer (a 
base32-encoded value)
+      wtid: WireTransferIdentifierRawP;
+
+      // target account that received the wire transfer
+      payto_uri: string;
+
+      // base URL of the exchange that made the wire transfer
+      exchange_url: string;
+    }
+  }
+
+  namespace OTP {
+    interface OtpDeviceAddDetails {
+      // Device ID to use.
+      otp_device_id: string;
+
+      // Human-readable description for the device.
+      otp_device_description: string;
+
+      // A base64-encoded key
+      otp_key: string;
+
+      // Algorithm for computing the POS confirmation.
+      otp_algorithm: Integer;
+
+      // Counter for counter-based OTP devices.
+      otp_ctr?: Integer;
+    }
+
+    interface OtpDevicePatchDetails {
+      // Human-readable description for the device.
+      otp_device_description: string;
+
+      // A base64-encoded key
+      otp_key: string | undefined;
+
+      // Algorithm for computing the POS confirmation.
+      otp_algorithm: Integer;
+
+      // Counter for counter-based OTP devices.
+      otp_ctr?: Integer;
+    }
+
+    interface OtpDeviceSummaryResponse {
+      // Array of devices that are present in our backend.
+      otp_devices: OtpDeviceEntry[];
+    }
+    interface OtpDeviceEntry {
+      // Device identifier.
+      otp_device_id: string;
+
+      // Human-readable description for the device.
+      device_description: string;
+    }
+
+    interface OtpDeviceDetails {
+      // Human-readable description for the device.
+      device_description: string;
+
+      // Algorithm for computing the POS confirmation.
+      otp_algorithm: Integer;
+
+      // Counter for counter-based OTP devices.
+      otp_ctr?: Integer;
+    }
+
+
+  }
+  namespace Template {
+    interface TemplateAddDetails {
+      // Template ID to use.
+      template_id: string;
+
+      // Human-readable description for the template.
+      template_description: string;
+
+      // OTP device ID.
+      // This parameter is optional.
+      otp_id?: string;
+
+      // Additional information in a separate template.
+      template_contract: TemplateContractDetails;
+    }
+    interface TemplateContractDetails {
+      // Human-readable summary for the template.
+      summary?: string;
+
+      // The price is imposed by the merchant and cannot be changed by the 
customer.
+      // This parameter is optional.
+      amount?: Amount;
+
+      // Minimum age buyer must have (in years). Default is 0.
+      minimum_age: Integer;
+
+      // The time the customer need to pay before his order will be deleted.
+      // It is deleted if the customer did not pay and if the duration is over.
+      pay_duration: RelativeTime;
+    }
+    interface TemplatePatchDetails {
+      // Human-readable description for the template.
+      template_description: string;
+
+      // OTP device ID.
+      // This parameter is optional.
+      otp_id?: string;
+
+      // Additional information in a separate template.
+      template_contract: TemplateContractDetails;
+    }
+
+    interface TemplateSummaryResponse {
+      // List of templates that are present in our backend.
+      templates: TemplateEntry[];
+    }
+
+    interface TemplateEntry {
+      // Template identifier, as found in the template.
+      template_id: string;
+
+      // Human-readable description for the template.
+      template_description: string;
+    }
+
+    interface TemplateDetails {
+      // Human-readable description for the template.
+      template_description: string;
+
+      // OTP device ID.
+      // This parameter is optional.
+      otp_id?: string;
+
+      // Additional information in a separate template.
+      template_contract: TemplateContractDetails;
+    }
+
+    interface UsingTemplateDetails {
+      // Subject of the template
+      summary?: string;
+
+      // The amount entered by the customer.
+      amount?: Amount;
+    }
+
+    interface UsingTemplateResponse {
+      // After enter the request. The user will be pay with a taler URL.
+      order_id: string;
+      token: string;
+    }
+  }
+
+  namespace Webhooks {
+    type MerchantWebhookType = "pay" | "refund";
+    interface WebhookAddDetails {
+      // Webhook ID to use.
+      webhook_id: string;
+
+      // The event of the webhook: why the webhook is used.
+      event_type: MerchantWebhookType;
+
+      // URL of the webhook where the customer will be redirected.
+      url: string;
+
+      // Method used by the webhook
+      http_method: string;
+
+      // Header template of the webhook
+      header_template?: string;
+
+      // Body template by the webhook
+      body_template?: string;
+    }
+    interface WebhookPatchDetails {
+      // The event of the webhook: why the webhook is used.
+      event_type: string;
+
+      // URL of the webhook where the customer will be redirected.
+      url: string;
+
+      // Method used by the webhook
+      http_method: string;
+
+      // Header template of the webhook
+      header_template?: string;
+
+      // Body template by the webhook
+      body_template?: string;
+    }
+    interface WebhookSummaryResponse {
+      // List of webhooks that are present in our backend.
+      webhooks: WebhookEntry[];
+    }
+    interface WebhookEntry {
+      // Webhook identifier, as found in the webhook.
+      webhook_id: string;
+
+      // The event of the webhook: why the webhook is used.
+      event_type: string;
+    }
+    interface WebhookDetails {
+      // The event of the webhook: why the webhook is used.
+      event_type: string;
+
+      // URL of the webhook where the customer will be redirected.
+      url: string;
+
+      // Method used by the webhook
+      http_method: string;
+
+      // Header template of the webhook
+      header_template?: string;
+
+      // Body template by the webhook
+      body_template?: string;
+    }
+  }
+
+  interface ContractTerms {
+    // Human-readable description of the whole purchase
+    summary: string;
+
+    // Map from IETF BCP 47 language tags to localized summaries
+    summary_i18n?: { [lang_tag: string]: string };
+
+    // Unique, free-form identifier for the proposal.
+    // Must be unique within a merchant instance.
+    // For merchants that do not store proposals in their DB
+    // before the customer paid for them, the order_id can be used
+    // by the frontend to restore a proposal from the information
+    // encoded in it (such as a short product identifier and timestamp).
+    order_id: string;
+
+    // Total price for the transaction.
+    // The exchange will subtract deposit fees from that amount
+    // before transferring it to the merchant.
+    amount: Amount;
+
+    // The URL for this purchase.  Every time is is visited, the merchant
+    // will send back to the customer the same proposal.  Clearly, this URL
+    // can be bookmarked and shared by users.
+    fulfillment_url?: string;
+
+    // Maximum total deposit fee accepted by the merchant for this contract
+    max_fee: Amount;
+
+    // List of products that are part of the purchase (see Product).
+    products: Product[];
+
+    // Time when this contract was generated
+    timestamp: TalerProtocolTimestamp;
+
+    // After this deadline has passed, no refunds will be accepted.
+    refund_deadline: TalerProtocolTimestamp;
+
+    // After this deadline, the merchant won't accept payments for the contact
+    pay_deadline: TalerProtocolTimestamp;
+
+    // Transfer deadline for the exchange.  Must be in the
+    // deposit permissions of coins used to pay for this order.
+    wire_transfer_deadline: TalerProtocolTimestamp;
+
+    // Merchant's public key used to sign this proposal; this information
+    // is typically added by the backend Note that this can be an ephemeral 
key.
+    merchant_pub: EddsaPublicKey;
+
+    // Base URL of the (public!) merchant backend API.
+    // Must be an absolute URL that ends with a slash.
+    merchant_base_url: string;
+
+    // More info about the merchant, see below
+    merchant: Merchant;
+
+    // The hash of the merchant instance's wire details.
+    h_wire: HashCode;
+
+    // Wire transfer method identifier for the wire method associated with 
h_wire.
+    // The wallet may only select exchanges via a matching auditor if the
+    // exchange also supports this wire method.
+    // The wire transfer fees must be added based on this wire transfer method.
+    wire_method: string;
+
+    // Any exchanges audited by these auditors are accepted by the merchant.
+    auditors: Auditor[];
+
+    // Exchanges that the merchant accepts even if it does not accept any 
auditors that audit them.
+    exchanges: Exchange[];
+
+    // Delivery location for (all!) products.
+    delivery_location?: Location;
+
+    // Time indicating when the order should be delivered.
+    // May be overwritten by individual products.
+    delivery_date?: TalerProtocolTimestamp;
+
+    // Nonce generated by the wallet and echoed by the merchant
+    // in this field when the proposal is generated.
+    nonce: string;
+
+    // Specifies for how long the wallet should try to get an
+    // automatic refund for the purchase. If this field is
+    // present, the wallet should wait for a few seconds after
+    // the purchase and then automatically attempt to obtain
+    // a refund.  The wallet should probe until "delay"
+    // after the payment was successful (i.e. via long polling
+    // or via explicit requests with exponential back-off).
+    //
+    // In particular, if the wallet is offline
+    // at that time, it MUST repeat the request until it gets
+    // one response from the merchant after the delay has expired.
+    // If the refund is granted, the wallet MUST automatically
+    // recover the payment.  This is used in case a merchant
+    // knows that it might be unable to satisfy the contract and
+    // desires for the wallet to attempt to get the refund without any
+    // customer interaction.  Note that it is NOT an error if the
+    // merchant does not grant a refund.
+    auto_refund?: RelativeTime;
+
+    // Extra data that is only interpreted by the merchant frontend.
+    // Useful when the merchant needs to store extra information on a
+    // contract without storing it separately in their database.
+    extra?: any;
+
+    // Minimum age buyer must have (in years). Default is 0.
+    minimum_age?: Integer;
+  }
+}
diff --git a/packages/auditor-backoffice-ui/src/hooks/async.ts 
b/packages/auditor-backoffice-ui/src/hooks/async.ts
new file mode 100644
index 000000000..f22badc88
--- /dev/null
+++ b/packages/auditor-backoffice-ui/src/hooks/async.ts
@@ -0,0 +1,77 @@
+/*
+ This file is part of GNU Taler
+ (C) 2021-2023 Taler Systems S.A.
+
+ GNU Taler is free software; you can redistribute it and/or modify it under the
+ terms of the GNU General Public License as published by the Free Software
+ Foundation; either version 3, or (at your option) any later version.
+
+ GNU Taler is distributed in the hope that it will be useful, but WITHOUT ANY
+ WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
+ A PARTICULAR PURPOSE.  See the GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License along with
+ GNU Taler; see the file COPYING.  If not, see <http://www.gnu.org/licenses/>
+ */
+
+/**
+ *
+ * @author Sebastian Javier Marchano (sebasjm)
+ */
+import { useState } from "preact/hooks";
+
+export interface Options {
+  slowTolerance: number;
+}
+
+export interface AsyncOperationApi<T> {
+  request: (...a: any) => void;
+  cancel: () => void;
+  data: T | undefined;
+  isSlow: boolean;
+  isLoading: boolean;
+  error: string | undefined;
+}
+
+export function useAsync<T>(
+  fn?: (...args: any) => Promise<T>,
+  { slowTolerance: tooLong }: Options = { slowTolerance: 1000 },
+): AsyncOperationApi<T> {
+  const [data, setData] = useState<T | undefined>(undefined);
+  const [isLoading, setLoading] = useState<boolean>(false);
+  const [error, setError] = useState<any>(undefined);
+  const [isSlow, setSlow] = useState(false);
+
+  const request = async (...args: any) => {
+    if (!fn) return;
+    setLoading(true);
+
+    const handler = setTimeout(() => {
+      setSlow(true);
+    }, tooLong);
+
+    try {
+      const result = await fn(...args);
+      setData(result);
+    } catch (error) {
+      setError(error);
+    }
+    setLoading(false);
+    setSlow(false);
+    clearTimeout(handler);
+  };
+
+  function cancel(): void {
+    setLoading(false);
+    setSlow(false);
+  }
+
+  return {
+    request,
+    cancel,
+    data,
+    isSlow,
+    isLoading,
+    error,
+  };
+}
diff --git a/packages/auditor-backoffice-ui/src/hooks/backend.ts 
b/packages/auditor-backoffice-ui/src/hooks/backend.ts
new file mode 100644
index 000000000..8d99546a8
--- /dev/null
+++ b/packages/auditor-backoffice-ui/src/hooks/backend.ts
@@ -0,0 +1,477 @@
+/*
+ This file is part of GNU Taler
+ (C) 2021-2023 Taler Systems S.A.
+
+ GNU Taler is free software; you can redistribute it and/or modify it under the
+ terms of the GNU General Public License as published by the Free Software
+ Foundation; either version 3, or (at your option) any later version.
+
+ GNU Taler is distributed in the hope that it will be useful, but WITHOUT ANY
+ WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
+ A PARTICULAR PURPOSE.  See the GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License along with
+ GNU Taler; see the file COPYING.  If not, see <http://www.gnu.org/licenses/>
+ */
+
+/**
+ *
+ * @author Sebastian Javier Marchano (sebasjm)
+ */
+
+import { AbsoluteTime, HttpStatusCode } from "@gnu-taler/taler-util";
+import {
+  ErrorType,
+  HttpError,
+  HttpResponse,
+  HttpResponseOk,
+  RequestError,
+  RequestOptions,
+  useApiContext,
+} from "@gnu-taler/web-util/browser";
+import { useCallback, useEffect, useState } from "preact/hooks";
+import { useSWRConfig } from "swr";
+import { useBackendContext } from "../context/backend.js";
+import { useInstanceContext } from "../context/instance.js";
+import { AccessToken, LoginToken, MerchantBackend, Timestamp } from 
"../declaration.js";
+
+
+export function useMatchMutate(): (
+  re?: RegExp,
+  value?: unknown,
+) => Promise<any> {
+  const { cache, mutate } = useSWRConfig();
+
+  if (!(cache instanceof Map)) {
+    throw new Error(
+      "matchMutate requires the cache provider to be a Map instance",
+    );
+  }
+
+  return function matchRegexMutate(re?: RegExp) {
+    return mutate((key) => {
+      // evict if no key or regex === all
+      if (!key || !re) return true
+      // match string
+      if (typeof key === 'string' && re.test(key)) return true
+      // record or object have the path at [0]
+      if (typeof key === 'object' && re.test(key[0])) return true
+      //key didn't match regex
+      return false
+    }, undefined, {
+      revalidate: true,
+    });
+  };
+}
+
+export function useBackendInstancesTestForAdmin(): HttpResponse<
+  MerchantBackend.Instances.InstancesResponse,
+  MerchantBackend.ErrorDetail
+> {
+  const { request } = useBackendBaseRequest();
+
+  type Type = MerchantBackend.Instances.InstancesResponse;
+
+  const [result, setResult] = useState<
+    HttpResponse<Type, MerchantBackend.ErrorDetail>
+  >({ loading: true });
+
+  useEffect(() => {
+    request<Type>(`/management/instances`)
+      .then((data) => setResult(data))
+      .catch((error: RequestError<MerchantBackend.ErrorDetail>) =>
+        setResult(error.cause),
+      );
+  }, [request]);
+
+  return result;
+}
+
+const CHECK_CONFIG_INTERVAL_OK = 5 * 60 * 1000;
+const CHECK_CONFIG_INTERVAL_FAIL = 2 * 1000;
+
+export function useBackendConfig(): HttpResponse<
+  MerchantBackend.VersionResponse | undefined,
+  RequestError<MerchantBackend.ErrorDetail>
+> {
+  const { request } = useBackendBaseRequest();
+
+  type Type = MerchantBackend.VersionResponse;
+  type State = { data: HttpResponse<Type, 
RequestError<MerchantBackend.ErrorDetail>>, timer: number }
+  const [result, setResult] = useState<State>({ data: { loading: true }, 
timer: 0 });
+
+  useEffect(() => {
+    if (result.timer) {
+      clearTimeout(result.timer)
+    }
+    function tryConfig(): void {
+      request<Type>(`/config`)
+        .then((data) => {
+          const timer: any = setTimeout(() => {
+            tryConfig()
+          }, CHECK_CONFIG_INTERVAL_OK)
+          setResult({ data, timer })
+        })
+        .catch((error) => {
+          const timer: any = setTimeout(() => {
+            tryConfig()
+          }, CHECK_CONFIG_INTERVAL_FAIL)
+          const data = error.cause
+          setResult({ data, timer })
+        });
+    }
+    tryConfig()
+  }, [request]);
+
+  return result.data;
+}
+
+interface useBackendInstanceRequestType {
+  request: <T>(
+    endpoint: string,
+    options?: RequestOptions,
+  ) => Promise<HttpResponseOk<T>>;
+  fetcher: <T>(endpoint: string) => Promise<HttpResponseOk<T>>;
+  reserveDetailFetcher: <T>(endpoint: string) => Promise<HttpResponseOk<T>>;
+  rewardsDetailFetcher: <T>(endpoint: string) => Promise<HttpResponseOk<T>>;
+  multiFetcher: <T>(params: [url: string[]]) => Promise<HttpResponseOk<T>[]>;
+  orderFetcher: <T>(
+    params: [endpoint: string,
+      paid?: YesOrNo,
+      refunded?: YesOrNo,
+      wired?: YesOrNo,
+      searchDate?: Date,
+      delta?: number,]
+  ) => Promise<HttpResponseOk<T>>;
+  transferFetcher: <T>(
+    params: [endpoint: string,
+      payto_uri?: string,
+      verified?: string,
+      position?: string,
+      delta?: number,]
+  ) => Promise<HttpResponseOk<T>>;
+  templateFetcher: <T>(
+    params: [endpoint: string,
+      position?: string,
+      delta?: number]
+  ) => Promise<HttpResponseOk<T>>;
+  webhookFetcher: <T>(
+    params: [endpoint: string,
+      position?: string,
+      delta?: number]
+  ) => Promise<HttpResponseOk<T>>;
+}
+interface useBackendBaseRequestType {
+  request: <T>(
+    endpoint: string,
+    options?: RequestOptions,
+  ) => Promise<HttpResponseOk<T>>;
+}
+
+type YesOrNo = "yes" | "no";
+type LoginResult = {
+  valid: true;
+  token: string;
+  expiration: Timestamp;
+} | {
+  valid: false;
+  cause: HttpError<{}>;
+}
+
+export function useCredentialsChecker() {
+  const { request } = useApiContext();
+  //check against instance details endpoint
+  //while merchant backend doesn't have a login endpoint
+  async function requestNewLoginToken(
+    baseUrl: string,
+    token: AccessToken,
+  ): Promise<LoginResult> {
+    const data: MerchantBackend.Instances.LoginTokenRequest = {
+      scope: "write",
+      duration: {
+        d_us: "forever"
+      },
+      refreshable: true,
+    }
+    try {
+      const response = await 
request<MerchantBackend.Instances.LoginTokenSuccessResponse>(baseUrl, 
`/private/token`, {
+        method: "POST",
+        token,
+        data
+      });
+      return { valid: true, token: response.data.token, expiration: 
response.data.expiration };
+    } catch (error) {
+      if (error instanceof RequestError) {
+        return { valid: false, cause: error.cause };
+      }
+
+      return {
+        valid: false, cause: {
+          type: ErrorType.UNEXPECTED,
+          loading: false,
+          info: {
+            hasToken: true,
+            status: 0,
+            options: {},
+            url: `/private/token`,
+            payload: {}
+          },
+          exception: error,
+          message: (error instanceof Error ? error.message : "unpexepected 
error")
+        }
+      };
+    }
+  };
+
+  async function refreshLoginToken(
+    baseUrl: string,
+    token: LoginToken
+  ): Promise<LoginResult> {
+
+    if 
(AbsoluteTime.isExpired(AbsoluteTime.fromProtocolTimestamp(token.expiration))) {
+      return {
+        valid: false, cause: {
+          type: ErrorType.CLIENT,
+          status: HttpStatusCode.Unauthorized,
+          message: "login token expired, login again.",
+          info: {
+            hasToken: true,
+            status: 401,
+            options: {},
+            url: `/private/token`,
+            payload: {}
+          },
+          payload: {}
+        },
+      }
+    }
+
+    return requestNewLoginToken(baseUrl, token.token as AccessToken)
+  }
+  return { requestNewLoginToken, refreshLoginToken }
+}
+
+/**
+ *
+ * @param root the request is intended to the base URL and no the instance URL
+ * @returns request handler to
+ */
+export function useBackendBaseRequest(): useBackendBaseRequestType {
+  const { url: backend, token: loginToken } = useBackendContext();
+  const { request: requestHandler } = useApiContext();
+  const token = loginToken?.token;
+
+  const request = useCallback(
+    function requestImpl<T>(
+      endpoint: string,
+      options: RequestOptions = {},
+    ): Promise<HttpResponseOk<T>> {
+      return requestHandler<T>(backend, endpoint, { ...options, token 
}).then(res => {
+        return res
+      }).catch(err => {
+        throw err
+      });
+    },
+    [backend, token],
+  );
+
+  return { request };
+}
+
+export function useBackendInstanceRequest(): useBackendInstanceRequestType {
+  const { url: rootBackendUrl, token: rootToken } = useBackendContext();
+  const { token: instanceToken, id, admin } = useInstanceContext();
+  const { request: requestHandler } = useApiContext();
+
+  const { baseUrl, token: loginToken } = !admin
+    ? { baseUrl: rootBackendUrl, token: rootToken }
+    : { baseUrl: `${rootBackendUrl}/instances/${id}`, token: instanceToken };
+
+  const token = loginToken?.token;
+
+  const request = useCallback(
+    function requestImpl<T>(
+      endpoint: string,
+      options: RequestOptions = {},
+    ): Promise<HttpResponseOk<T>> {
+      return requestHandler<T>(baseUrl, endpoint, { token, ...options });
+    },
+    [baseUrl, token],
+  );
+
+  const multiFetcher = useCallback(
+    function multiFetcherImpl<T>(
+      args: [endpoints: string[]],
+    ): Promise<HttpResponseOk<T>[]> {
+      const [endpoints] = args
+      return Promise.all(
+        endpoints.map((endpoint) =>
+          requestHandler<T>(baseUrl, endpoint, { token }),
+        ),
+      );
+    },
+    [baseUrl, token],
+  );
+
+  const fetcher = useCallback(
+    function fetcherImpl<T>(endpoint: string): Promise<HttpResponseOk<T>> {
+      return requestHandler<T>(baseUrl, endpoint, { token });
+    },
+    [baseUrl, token],
+  );
+
+  const orderFetcher = useCallback(
+    function orderFetcherImpl<T>(
+      args: [endpoint: string,
+        paid?: YesOrNo,
+        refunded?: YesOrNo,
+        wired?: YesOrNo,
+        searchDate?: Date,
+        delta?: number,]
+    ): Promise<HttpResponseOk<T>> {
+      const [endpoint, paid, refunded, wired, searchDate, delta] = args
+      const date_s =
+        delta && delta < 0 && searchDate
+          ? Math.floor(searchDate.getTime() / 1000) + 1
+          : searchDate !== undefined ? Math.floor(searchDate.getTime() / 1000) 
: undefined;
+      const params: any = {};
+      if (paid !== undefined) params.paid = paid;
+      if (delta !== undefined) params.delta = delta;
+      if (refunded !== undefined) params.refunded = refunded;
+      if (wired !== undefined) params.wired = wired;
+      if (date_s !== undefined) params.date_s = date_s;
+      if (delta === 0) {
+        //in this case we can already assume the response 
+        //and avoid network
+        return Promise.resolve({
+          ok: true,
+          data: { orders: [] } as T,
+        })
+      }
+      return requestHandler<T>(baseUrl, endpoint, { params, token });
+    },
+    [baseUrl, token],
+  );
+
+  const reserveDetailFetcher = useCallback(
+    function reserveDetailFetcherImpl<T>(
+      endpoint: string,
+    ): Promise<HttpResponseOk<T>> {
+      return requestHandler<T>(baseUrl, endpoint, {
+        params: {
+          rewards: "yes",
+        },
+        token,
+      });
+    },
+    [baseUrl, token],
+  );
+
+  const rewardsDetailFetcher = useCallback(
+    function rewardsDetailFetcherImpl<T>(
+      endpoint: string,
+    ): Promise<HttpResponseOk<T>> {
+      return requestHandler<T>(baseUrl, endpoint, {
+        params: {
+          pickups: "yes",
+        },
+        token,
+      });
+    },
+    [baseUrl, token],
+  );
+
+  const transferFetcher = useCallback(
+    function transferFetcherImpl<T>(
+      args: [endpoint: string,
+        payto_uri?: string,
+        verified?: string,
+        position?: string,
+        delta?: number,]
+    ): Promise<HttpResponseOk<T>> {
+      const [endpoint, payto_uri, verified, position, delta] = args
+      const params: any = {};
+      if (payto_uri !== undefined) params.payto_uri = payto_uri;
+      if (verified !== undefined) params.verified = verified;
+      if (delta === 0) {
+        //in this case we can already assume the response 
+        //and avoid network
+        return Promise.resolve({
+          ok: true,
+          data: { transfers: [] } as T,
+        })
+      }
+      if (delta !== undefined) {
+        params.limit = delta;
+      }
+      if (position !== undefined) params.offset = position;
+
+      return requestHandler<T>(baseUrl, endpoint, { params, token });
+    },
+    [baseUrl, token],
+  );
+
+  const templateFetcher = useCallback(
+    function templateFetcherImpl<T>(
+      args: [endpoint: string,
+        position?: string,
+        delta?: number,]
+    ): Promise<HttpResponseOk<T>> {
+      const [endpoint, position, delta] = args
+      const params: any = {};
+      if (delta === 0) {
+        //in this case we can already assume the response 
+        //and avoid network
+        return Promise.resolve({
+          ok: true,
+          data: { templates: [] } as T,
+        })
+      }
+      if (delta !== undefined) {
+        params.limit = delta;
+      }
+      if (position !== undefined) params.offset = position;
+
+      return requestHandler<T>(baseUrl, endpoint, { params, token });
+    },
+    [baseUrl, token],
+  );
+
+  const webhookFetcher = useCallback(
+    function webhookFetcherImpl<T>(
+      args: [endpoint: string,
+        position?: string,
+        delta?: number,]
+    ): Promise<HttpResponseOk<T>> {
+      const [endpoint, position, delta] = args
+      const params: any = {};
+      if (delta === 0) {
+        //in this case we can already assume the response 
+        //and avoid network
+        return Promise.resolve({
+          ok: true,
+          data: { webhooks: [] } as T,
+        })
+      }
+      if (delta !== undefined) {
+        params.limit = delta;
+      }
+      if (position !== undefined) params.offset = position;
+
+      return requestHandler<T>(baseUrl, endpoint, { params, token });
+    },
+    [baseUrl, token],
+  );
+
+  return {
+    request,
+    fetcher,
+    multiFetcher,
+    orderFetcher,
+    reserveDetailFetcher,
+    rewardsDetailFetcher,
+    transferFetcher,
+    templateFetcher,
+    webhookFetcher,
+  };
+}
diff --git a/packages/auditor-backoffice-ui/src/hooks/bank.ts 
b/packages/auditor-backoffice-ui/src/hooks/bank.ts
new file mode 100644
index 000000000..03b064646
--- /dev/null
+++ b/packages/auditor-backoffice-ui/src/hooks/bank.ts
@@ -0,0 +1,217 @@
+/*
+ This file is part of GNU Taler
+ (C) 2021-2023 Taler Systems S.A.
+
+ GNU Taler is free software; you can redistribute it and/or modify it under the
+ terms of the GNU General Public License as published by the Free Software
+ Foundation; either version 3, or (at your option) any later version.
+
+ GNU Taler is distributed in the hope that it will be useful, but WITHOUT ANY
+ WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
+ A PARTICULAR PURPOSE.  See the GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License along with
+ GNU Taler; see the file COPYING.  If not, see <http://www.gnu.org/licenses/>
+ */
+import {
+  HttpResponse,
+  HttpResponseOk,
+  HttpResponsePaginated,
+  RequestError,
+} from "@gnu-taler/web-util/browser";
+import { useEffect, useState } from "preact/hooks";
+import { MerchantBackend } from "../declaration.js";
+import { MAX_RESULT_SIZE, PAGE_SIZE } from "../utils/constants.js";
+import { useBackendInstanceRequest, useMatchMutate } from "./backend.js";
+
+// FIX default import https://github.com/microsoft/TypeScript/issues/49189
+import _useSWR, { SWRHook } from "swr";
+const useSWR = _useSWR as unknown as SWRHook;
+
+// const MOCKED_ACCOUNTS: Record<string, 
MerchantBackend.BankAccounts.AccountAddDetails> = {
+//   "hwire1": {
+//     h_wire: "hwire1",
+//     payto_uri: "payto://fake/iban/123",
+//     salt: "qwe",
+//   },
+//   "hwire2": {
+//     h_wire: "hwire2",
+//     payto_uri: "payto://fake/iban/123",
+//     salt: "qwe2",
+//   },
+// }
+
+export function useBankAccountAPI(): BankAccountAPI {
+  const mutateAll = useMatchMutate();
+  const { request } = useBackendInstanceRequest();
+
+  const createBankAccount = async (
+    data: MerchantBackend.BankAccounts.AccountAddDetails,
+  ): Promise<HttpResponseOk<void>> => {
+    // MOCKED_ACCOUNTS[data.h_wire] = data
+    // return Promise.resolve({ ok: true, data: undefined });
+    const res = await request<void>(`/private/accounts`, {
+      method: "POST",
+      data,
+    });
+    await mutateAll(/.*private\/accounts.*/);
+    return res;
+  };
+
+  const updateBankAccount = async (
+    h_wire: string,
+    data: MerchantBackend.BankAccounts.AccountPatchDetails,
+  ): Promise<HttpResponseOk<void>> => {
+    // MOCKED_ACCOUNTS[h_wire].credit_facade_credentials = 
data.credit_facade_credentials
+    // MOCKED_ACCOUNTS[h_wire].credit_facade_url = data.credit_facade_url
+    // return Promise.resolve({ ok: true, data: undefined });
+    const res = await request<void>(`/private/accounts/${h_wire}`, {
+      method: "PATCH",
+      data,
+    });
+    await mutateAll(/.*private\/accounts.*/);
+    return res;
+  };
+
+  const deleteBankAccount = async (
+    h_wire: string,
+  ): Promise<HttpResponseOk<void>> => {
+    // delete MOCKED_ACCOUNTS[h_wire]
+    // return Promise.resolve({ ok: true, data: undefined });
+    const res = await request<void>(`/private/accounts/${h_wire}`, {
+      method: "DELETE",
+    });
+    await mutateAll(/.*private\/accounts.*/);
+    return res;
+  };
+
+  return {
+    createBankAccount,
+    updateBankAccount,
+    deleteBankAccount,
+  };
+}
+
+export interface BankAccountAPI {
+  createBankAccount: (
+    data: MerchantBackend.BankAccounts.AccountAddDetails,
+  ) => Promise<HttpResponseOk<void>>;
+  updateBankAccount: (
+    id: string,
+    data: MerchantBackend.BankAccounts.AccountPatchDetails,
+  ) => Promise<HttpResponseOk<void>>;
+  deleteBankAccount: (id: string) => Promise<HttpResponseOk<void>>;
+}
+
+export interface InstanceBankAccountFilter {
+}
+
+export function useInstanceBankAccounts(
+  args?: InstanceBankAccountFilter,
+  updatePosition?: (id: string) => void,
+): HttpResponsePaginated<
+  MerchantBackend.BankAccounts.AccountsSummaryResponse,
+  MerchantBackend.ErrorDetail
+> {
+  // return {
+  //   ok: true,
+  //   loadMore() { },
+  //   loadMorePrev() { },
+  //   data: {
+  //     accounts: Object.values(MOCKED_ACCOUNTS).map(e => ({
+  //       ...e,
+  //       active: true,
+  //     }))
+  //   }
+  // }
+  const { fetcher } = useBackendInstanceRequest();
+
+  const [pageAfter, setPageAfter] = useState(1);
+
+  const totalAfter = pageAfter * PAGE_SIZE;
+  const {
+    data: afterData,
+    error: afterError,
+    isValidating: loadingAfter,
+  } = useSWR<
+    HttpResponseOk<MerchantBackend.BankAccounts.AccountsSummaryResponse>,
+    RequestError<MerchantBackend.ErrorDetail>
+  >([`/private/accounts`], fetcher);
+
+  const [lastAfter, setLastAfter] = useState<
+    HttpResponse<
+      MerchantBackend.BankAccounts.AccountsSummaryResponse,
+      MerchantBackend.ErrorDetail
+    >
+  >({ loading: true });
+  useEffect(() => {
+    if (afterData) setLastAfter(afterData);
+  }, [afterData /*, beforeData*/]);
+
+  if (afterError) return afterError.cause;
+
+  // if the query returns less that we ask, then we have reach the end or 
beginning
+  const isReachingEnd =
+    afterData && afterData.data.accounts.length < totalAfter;
+  const isReachingStart = false;
+
+  const pagination = {
+    isReachingEnd,
+    isReachingStart,
+    loadMore: () => {
+      if (!afterData || isReachingEnd) return;
+      if (afterData.data.accounts.length < MAX_RESULT_SIZE) {
+        setPageAfter(pageAfter + 1);
+      } else {
+        const from = `${afterData.data.accounts[afterData.data.accounts.length 
- 1]
+          .h_wire
+          }`;
+        if (from && updatePosition) updatePosition(from);
+      }
+    },
+    loadMorePrev: () => {
+    },
+  };
+
+  const accounts = !afterData ? [] : (afterData || lastAfter).data.accounts;
+  if (loadingAfter /* || loadingBefore */)
+    return { loading: true, data: { accounts } };
+  if (/*beforeData &&*/ afterData) {
+    return { ok: true, data: { accounts }, ...pagination };
+  }
+  return { loading: true };
+}
+
+export function useBankAccountDetails(
+  h_wire: string,
+): HttpResponse<
+  MerchantBackend.BankAccounts.BankAccountEntry,
+  MerchantBackend.ErrorDetail
+> {
+  // return {
+  //   ok: true,
+  //   data: {
+  //     ...MOCKED_ACCOUNTS[h_wire],
+  //     active: true,
+  //   }
+  // }
+  const { fetcher } = useBackendInstanceRequest();
+
+  const { data, error, isValidating } = useSWR<
+    HttpResponseOk<MerchantBackend.BankAccounts.BankAccountEntry>,
+    RequestError<MerchantBackend.ErrorDetail>
+  >([`/private/accounts/${h_wire}`], fetcher, {
+    refreshInterval: 0,
+    refreshWhenHidden: false,
+    revalidateOnFocus: false,
+    revalidateOnReconnect: false,
+    refreshWhenOffline: false,
+  });
+
+  if (isValidating) return { loading: true, data: data?.data };
+  if (data) {
+    return data;
+  }
+  if (error) return error.cause;
+  return { loading: true };
+}
diff --git a/packages/auditor-backoffice-ui/src/hooks/deposit_confirmations.ts 
b/packages/auditor-backoffice-ui/src/hooks/deposit_confirmations.ts
new file mode 100644
index 000000000..e4ec9a2f2
--- /dev/null
+++ b/packages/auditor-backoffice-ui/src/hooks/deposit_confirmations.ts
@@ -0,0 +1,161 @@
+/*
+ This file is part of GNU Taler
+ (C) 2021-2024 Taler Systems S.A.
+
+ GNU Taler is free software; you can redistribute it and/or modify it under the
+ terms of the GNU General Public License as published by the Free Software
+ Foundation; either version 3, or (at your option) any later version.
+
+ GNU Taler is distributed in the hope that it will be useful, but WITHOUT ANY
+ WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
+ A PARTICULAR PURPOSE.  See the GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License along with
+ GNU Taler; see the file COPYING.  If not, see <http://www.gnu.org/licenses/>
+ */
+import {
+  HttpResponse,
+  HttpResponseOk,
+  RequestError,
+} from "@gnu-taler/web-util/browser";
+import { AuditorBackend, MerchantBackend, WithId } from "../declaration.js";
+import { useBackendInstanceRequest, useMatchMutate } from "./backend.js";
+
+// FIX default import https://github.com/microsoft/TypeScript/issues/49189
+import _useSWR, { SWRHook, useSWRConfig } from "swr";
+const useSWR = _useSWR as unknown as SWRHook;
+
+export interface DepositConfirmationAPI {
+  getDepositConfirmation: (
+    id: string,
+  ) => Promise<void>;
+  createDepositConfirmation: (
+    data: MerchantBackend.Products.ProductAddDetail,
+  ) => Promise<void>;
+  updateDepositConfirmation: (
+    id: string,
+    data: MerchantBackend.Products.ProductPatchDetail,
+  ) => Promise<void>;
+  deleteDepositConfirmation: (id: string) => Promise<void>;
+}
+
+export function useDepositConfirmationAPI(): DepositConfirmationAPI {
+  const mutateAll = useMatchMutate();
+  const { mutate } = useSWRConfig();
+
+  const { request } = useBackendInstanceRequest();
+
+  const createDepositConfirmation = async (
+    data: MerchantBackend.Products.ProductAddDetail,
+  ): Promise<void> => {
+    const res = await request(`/private/products`, {
+      method: "POST",
+      data,
+    });
+
+    return await mutateAll(/.*\/private\/products.*/);
+  };
+
+  const updateDepositConfirmation = async (
+    productId: string,
+    data: MerchantBackend.Products.ProductPatchDetail,
+  ): Promise<void> => {
+    const r = await request(`/private/products/${productId}`, {
+      method: "PATCH",
+      data,
+    });
+
+    return await mutateAll(/.*\/private\/products.*/);
+  };
+
+  const deleteDepositConfirmation = async (productId: string): Promise<void> 
=> {
+    await request(`/private/products/${productId}`, {
+      method: "DELETE",
+    });
+    await mutate([`/private/products`]);
+  };
+
+  const getDepositConfirmation = async (
+    serialId: string,
+  ): Promise<void> => {
+    await request(`/deposit-confirmation/${serialId}`, {
+      method: "GET",
+    });
+
+    return
+  };
+
+  return {createDepositConfirmation, updateDepositConfirmation, 
deleteDepositConfirmation, getDepositConfirmation};
+}
+
+export function useDepositConfirmation(): HttpResponse<
+  (AuditorBackend.DepositConfirmation.DepositConfirmationDetail & WithId)[],
+  AuditorBackend.ErrorDetail
+> {
+  const { fetcher, multiFetcher } = useBackendInstanceRequest();
+
+  const { data: list, error: listError } = useSWR<
+    HttpResponseOk<AuditorBackend.DepositConfirmation.DepositConfirmationList>,
+    RequestError<AuditorBackend.ErrorDetail>
+  >([`/deposit-confirmation`], fetcher, {
+    refreshInterval: 0,
+    refreshWhenHidden: false,
+    revalidateOnFocus: false,
+    revalidateOnReconnect: false,
+    refreshWhenOffline: false,
+  });
+
+  const paths = (list?.data.depositConfirmations || []).map(
+    (p) => `/deposit-confirmation/${p.serial_id}`,
+  );
+  const { data: depositConfirmations, error: depositConfirmationError } = 
useSWR<
+    
HttpResponseOk<AuditorBackend.DepositConfirmation.DepositConfirmationDetail>[],
+    RequestError<AuditorBackend.ErrorDetail>
+  >([paths], multiFetcher, {
+    refreshInterval: 0,
+    refreshWhenHidden: false,
+    revalidateOnFocus: false,
+    revalidateOnReconnect: false,
+    refreshWhenOffline: false,
+  });
+
+  if (listError) return listError.cause;
+  if (depositConfirmationError) return depositConfirmationError.cause;
+
+  if (depositConfirmations) {
+    const dataWithId = depositConfirmations.map((d) => {
+      //take the id from the queried url
+      return {
+        ...d.data,
+        id: d.info?.url.replace(/.*\/deposit-confirmation\//, "") || "",
+      };
+    });
+    return { ok: true, data: dataWithId };
+  }
+  return { loading: true };
+}
+
+export function useDepositConfirmationDetails(
+  serialId: string,
+): HttpResponse<
+  AuditorBackend.DepositConfirmation.DepositConfirmationDetail,
+  AuditorBackend.ErrorDetail
+> {
+  const { fetcher } = useBackendInstanceRequest();
+
+  const { data, error, isValidating } = useSWR<
+    
HttpResponseOk<AuditorBackend.DepositConfirmation.DepositConfirmationDetail>,
+    RequestError<AuditorBackend.ErrorDetail>
+  >([`/deposit-confirmation/${serialId}`], fetcher, {
+    refreshInterval: 0,
+    refreshWhenHidden: false,
+    revalidateOnFocus: false,
+    revalidateOnReconnect: false,
+    refreshWhenOffline: false,
+  });
+
+  if (isValidating) return { loading: true, data: data?.data };
+  if (data) return data;
+  if (error) return error.cause;
+  return { loading: true };
+}
diff --git a/packages/auditor-backoffice-ui/src/hooks/index.ts 
b/packages/auditor-backoffice-ui/src/hooks/index.ts
new file mode 100644
index 000000000..61afbc94a
--- /dev/null
+++ b/packages/auditor-backoffice-ui/src/hooks/index.ts
@@ -0,0 +1,151 @@
+/*
+ This file is part of GNU Taler
+ (C) 2021-2024 Taler Systems S.A.
+
+ GNU Taler is free software; you can redistribute it and/or modify it under the
+ terms of the GNU General Public License as published by the Free Software
+ Foundation; either version 3, or (at your option) any later version.
+
+ GNU Taler is distributed in the hope that it will be useful, but WITHOUT ANY
+ WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
+ A PARTICULAR PURPOSE.  See the GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License along with
+ GNU Taler; see the file COPYING.  If not, see <http://www.gnu.org/licenses/>
+ */
+
+/**
+ *
+ * @author Sebastian Javier Marchano (sebasjm)
+ */
+
+import { buildCodecForObject, codecForMap, codecForString, codecForTimestamp } 
from "@gnu-taler/taler-util";
+import { buildStorageKey, useLocalStorage } from "@gnu-taler/web-util/browser";
+import { StateUpdater, useEffect, useState } from "preact/hooks";
+import { LoginToken } from "../declaration.js";
+import { ValueOrFunction } from "../utils/types.js";
+import { useMatchMutate } from "./backend.js";
+
+const calculateRootPath = () => {
+  const rootPath =
+    typeof window !== undefined
+      ? window.location.origin + window.location.pathname
+      : "/";
+
+  /**
+   * By default, merchant backend serves the html content
+   * from the /webui root. This should cover most of the 
+   * cases and the rootPath will be the merchant backend
+   * URL where the instances are
+   */
+  return rootPath.replace("/webui/", "");
+};
+
+const loginTokenCodec = buildCodecForObject<LoginToken>()
+  .property("token", codecForString())
+  .property("expiration", codecForTimestamp)
+  .build("loginToken")
+const TOKENS_KEY = buildStorageKey("auditor-token", 
codecForMap(loginTokenCodec));
+
+
+export function useBackendURL(
+  url?: string,
+): [string, StateUpdater<string>] {
+  const [value, setter] = useSimpleLocalStorage(
+    "auditor-base-url",
+    url || calculateRootPath(),
+  );
+
+  const checkedSetter = (v: ValueOrFunction<string>) => {
+    return setter((p) => (v instanceof Function ? v(p ?? "") : 
v).replace(/\/$/, ""));
+  };
+
+  return [value!, checkedSetter];
+}
+
+export function useBackendDefaultToken(
+): [LoginToken | undefined, ((d: LoginToken | undefined) => void)] {
+  const { update: setToken, value: tokenMap, reset } = 
useLocalStorage(TOKENS_KEY, {})
+
+  const tokenOfDefaultInstance = tokenMap["default"]
+  const clearCache = useMatchMutate()
+  useEffect(() => {
+    clearCache()
+  }, [tokenOfDefaultInstance])
+
+  function updateToken(
+    value: (LoginToken | undefined)
+  ): void {
+    if (value === undefined) {
+      reset()
+    } else {
+      const res = { ...tokenMap, "default": value }
+      setToken(res)
+    }
+  }
+  return [tokenMap["default"], updateToken];
+}
+
+export function useBackendInstanceToken(
+  id: string,
+): [LoginToken | undefined, ((d: LoginToken | undefined) => void)] {
+  const { update: setToken, value: tokenMap, reset } = 
useLocalStorage(TOKENS_KEY, {})
+  const [defaultToken, defaultSetToken] = useBackendDefaultToken();
+
+  // instance named 'default' use the default token
+  if (id === "default") {
+    return [defaultToken, defaultSetToken];
+  }
+  function updateToken(
+    value: (LoginToken | undefined)
+  ): void {
+    if (value === undefined) {
+      reset()
+    } else {
+      const res = { ...tokenMap, [id]: value }
+      setToken(res)
+    }
+  }
+
+  return [tokenMap[id], updateToken];
+}
+
+export function useLang(initial?: string): [string, StateUpdater<string>] {
+  const browserLang =
+    typeof window !== "undefined"
+      ? navigator.language || (navigator as any).userLanguage
+      : undefined;
+  const defaultLang = (browserLang || initial || "en").substring(0, 2);
+  return useSimpleLocalStorage("lang-preference", defaultLang) as [string, 
StateUpdater<string>];
+}
+
+export function useSimpleLocalStorage(
+  key: string,
+  initialValue?: string,
+): [string | undefined, StateUpdater<string | undefined>] {
+  const [storedValue, setStoredValue] = useState<string | undefined>(
+    (): string | undefined => {
+      return typeof window !== "undefined"
+        ? window.localStorage.getItem(key) || initialValue
+        : initialValue;
+    },
+  );
+
+  const setValue = (
+    value?: string | ((val?: string) => string | undefined),
+  ) => {
+    setStoredValue((p) => {
+      const toStore = value instanceof Function ? value(p) : value;
+      if (typeof window !== "undefined") {
+        if (!toStore) {
+          window.localStorage.removeItem(key);
+        } else {
+          window.localStorage.setItem(key, toStore);
+        }
+      }
+      return toStore;
+    });
+  };
+
+  return [storedValue, setValue];
+}
diff --git a/packages/auditor-backoffice-ui/src/hooks/instance.test.ts 
b/packages/auditor-backoffice-ui/src/hooks/instance.test.ts
new file mode 100644
index 000000000..ee1576764
--- /dev/null
+++ b/packages/auditor-backoffice-ui/src/hooks/instance.test.ts
@@ -0,0 +1,741 @@
+/*
+ This file is part of GNU Taler
+ (C) 2021-2023 Taler Systems S.A.
+
+ GNU Taler is free software; you can redistribute it and/or modify it under the
+ terms of the GNU General Public License as published by the Free Software
+ Foundation; either version 3, or (at your option) any later version.
+
+ GNU Taler is distributed in the hope that it will be useful, but WITHOUT ANY
+ WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
+ A PARTICULAR PURPOSE.  See the GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License along with
+ GNU Taler; see the file COPYING.  If not, see <http://www.gnu.org/licenses/>
+ */
+
+/**
+ *
+ * @author Sebastian Javier Marchano (sebasjm)
+ */
+
+import * as tests from "@gnu-taler/web-util/testing";
+import { expect } from "chai";
+import { AccessToken, MerchantBackend } from "../declaration.js";
+import {
+  useAdminAPI,
+  useBackendInstances,
+  useInstanceAPI,
+  useInstanceDetails,
+  useManagementAPI,
+} from "./instance.js";
+import { ApiMockEnvironment } from "./testing.js";
+import {
+  API_CREATE_INSTANCE,
+  API_DELETE_INSTANCE,
+  API_GET_CURRENT_INSTANCE,
+  API_LIST_INSTANCES,
+  API_NEW_LOGIN,
+  API_UPDATE_CURRENT_INSTANCE,
+  API_UPDATE_CURRENT_INSTANCE_AUTH,
+  API_UPDATE_INSTANCE_BY_ID,
+} from "./urls.js";
+
+describe("instance api interaction with details", () => {
+  it("should evict cache when updating an instance", async () => {
+    const env = new ApiMockEnvironment();
+
+    env.addRequestExpectation(API_GET_CURRENT_INSTANCE, {
+      response: {
+        name: "instance_name",
+      } as MerchantBackend.Instances.QueryInstancesResponse,
+    });
+
+    const hookBehavior = await tests.hookBehaveLikeThis(
+      () => {
+        const api = useInstanceAPI();
+        const query = useInstanceDetails();
+        return { query, api };
+      },
+      {},
+      [
+        ({ query, api }) => {
+          expect(query.loading).true;
+        },
+        ({ query, api }) => {
+          expect(env.assertJustExpectedRequestWereMade()).deep.eq({
+            result: "ok",
+          });
+
+          expect(query.loading).false;
+          expect(query.ok).true;
+          if (!query.ok) return;
+          expect(query.data).deep.equals({
+            name: "instance_name",
+          });
+          env.addRequestExpectation(API_UPDATE_CURRENT_INSTANCE, {
+            request: {
+              name: "other_name",
+            } as MerchantBackend.Instances.InstanceReconfigurationMessage,
+          });
+          env.addRequestExpectation(API_GET_CURRENT_INSTANCE, {
+            response: {
+              name: "other_name",
+            } as MerchantBackend.Instances.QueryInstancesResponse,
+          });
+          api.updateInstance({
+            name: "other_name",
+          } as MerchantBackend.Instances.InstanceReconfigurationMessage);
+        },
+        ({ query, api }) => {
+          expect(env.assertJustExpectedRequestWereMade()).deep.eq({
+            result: "ok",
+          });
+          expect(query.loading).false;
+          expect(query.ok).true;
+          if (!query.ok) return;
+          expect(query.data).deep.equals({
+            name: "other_name",
+          });
+        },
+      ],
+      env.buildTestingContext(),
+    );
+
+    expect(hookBehavior).deep.eq({ result: "ok" });
+    expect(env.assertJustExpectedRequestWereMade()).deep.eq({ result: "ok" });
+  });
+
+  it("should evict cache when setting the instance's token", async () => {
+    const env = new ApiMockEnvironment();
+
+    env.addRequestExpectation(API_GET_CURRENT_INSTANCE, {
+      response: {
+        name: "instance_name",
+        auth: {
+          method: "token",
+          // token: "not-secret",
+        },
+      } as MerchantBackend.Instances.QueryInstancesResponse,
+    });
+
+    const hookBehavior = await tests.hookBehaveLikeThis(
+      () => {
+        const api = useInstanceAPI();
+        const query = useInstanceDetails();
+        return { query, api };
+      },
+      {},
+      [
+        ({ query, api }) => {
+          expect(query.loading).true;
+        },
+        ({ query, api }) => {
+          expect(env.assertJustExpectedRequestWereMade()).deep.eq({
+            result: "ok",
+          });
+          expect(query.loading).false;
+          expect(query.ok).true;
+          if (!query.ok) return;
+          expect(query.data).deep.equals({
+            name: "instance_name",
+            auth: {
+              method: "token",
+            },
+          });
+          env.addRequestExpectation(API_UPDATE_CURRENT_INSTANCE_AUTH, {
+            request: {
+              method: "token",
+              token: "secret",
+            } as MerchantBackend.Instances.InstanceAuthConfigurationMessage,
+          });
+          env.addRequestExpectation(API_NEW_LOGIN, {
+            auth: "secret",
+            request: {
+              scope: "write",
+              duration: {
+                "d_us": "forever",
+              },
+              refreshable: true,
+            },            
+          });
+          env.addRequestExpectation(API_GET_CURRENT_INSTANCE, {
+            response: {
+              name: "instance_name",
+              auth: {
+                method: "token",
+                // token: "secret",
+              },
+            } as MerchantBackend.Instances.QueryInstancesResponse,
+          });
+          api.setNewAccessToken(undefined, "secret" as AccessToken);
+        },
+        ({ query, api }) => {
+          expect(env.assertJustExpectedRequestWereMade()).deep.eq({
+            result: "ok",
+          });
+          expect(query.loading).false;
+          expect(query.ok).true;
+          if (!query.ok) return;
+          expect(query.data).deep.equals({
+            name: "instance_name",
+            auth: {
+              method: "token",
+              // token: "secret",
+            },
+          });
+        },
+      ],
+      env.buildTestingContext(),
+    );
+    expect(hookBehavior).deep.eq({ result: "ok" });
+    expect(env.assertJustExpectedRequestWereMade()).deep.eq({ result: "ok" });
+  });
+
+  it("should evict cache when clearing the instance's token", async () => {
+    const env = new ApiMockEnvironment();
+
+    env.addRequestExpectation(API_GET_CURRENT_INSTANCE, {
+      response: {
+        name: "instance_name",
+        auth: {
+          method: "token",
+          // token: "not-secret",
+        },
+      } as MerchantBackend.Instances.QueryInstancesResponse,
+    });
+
+    const hookBehavior = await tests.hookBehaveLikeThis(
+      () => {
+        const api = useInstanceAPI();
+        const query = useInstanceDetails();
+        return { query, api };
+      },
+      {},
+      [
+        ({ query, api }) => {
+          expect(query.loading).true;
+        },
+        ({ query, api }) => {
+          expect(env.assertJustExpectedRequestWereMade()).deep.eq({
+            result: "ok",
+          });
+          expect(query.loading).false;
+          expect(query.ok).true;
+          if (!query.ok) return;
+          expect(query.data).deep.equals({
+            name: "instance_name",
+            auth: {
+              method: "token",
+              // token: "not-secret",
+            },
+          });
+          env.addRequestExpectation(API_UPDATE_CURRENT_INSTANCE_AUTH, {
+            request: {
+              method: "external",
+            } as MerchantBackend.Instances.InstanceAuthConfigurationMessage,
+          });
+          env.addRequestExpectation(API_GET_CURRENT_INSTANCE, {
+            response: {
+              name: "instance_name",
+              auth: {
+                method: "external",
+              },
+            } as MerchantBackend.Instances.QueryInstancesResponse,
+          });
+
+          api.clearAccessToken(undefined);
+        },
+        ({ query, api }) => {
+          expect(env.assertJustExpectedRequestWereMade()).deep.eq({
+            result: "ok",
+          });
+          expect(query.loading).false;
+          expect(query.ok).true;
+          if (!query.ok) return;
+          expect(query.data).deep.equals({
+            name: "instance_name",
+            auth: {
+              method: "external",
+            },
+          });
+        },
+      ],
+      env.buildTestingContext(),
+    );
+    expect(hookBehavior).deep.eq({ result: "ok" });
+    expect(env.assertJustExpectedRequestWereMade()).deep.eq({ result: "ok" });
+    // const { result, waitForNextUpdate } = renderHook(
+    //   () => {
+    //     const api = useInstanceAPI();
+    //     const query = useInstanceDetails();
+
+    //     return { query, api };
+    //   },
+    //   { wrapper: TestingContext }
+    // );
+
+    // expect(result.current).not.undefined;
+    // if (!result.current) {
+    //   return;
+    // }
+    // expect(result.current.query.loading).true;
+
+    // await waitForNextUpdate({ timeout: 1 });
+
+    // expect(env.assertJustExpectedRequestWereMade()).deep.eq({ result: "ok" 
});
+
+    // expect(result.current.query.loading).false;
+
+    // expect(result.current?.query.ok).true;
+    // if (!result.current?.query.ok) return;
+
+    // expect(result.current.query.data).equals({
+    //   name: 'instance_name',
+    //   auth: {
+    //     method: 'token',
+    //     token: 'not-secret',
+    //   }
+    // });
+
+    // act(async () => {
+    //   await result.current?.api.clearToken();
+    // });
+
+    // expect(env.assertJustExpectedRequestWereMade()).deep.eq({ result: "ok" 
});
+
+    // expect(result.current.query.loading).false;
+
+    // await waitForNextUpdate({ timeout: 1 });
+
+    // expect(env.assertJustExpectedRequestWereMade()).deep.eq({ result: "ok" 
});
+
+    // expect(result.current.query.loading).false;
+    // expect(result.current.query.ok).true;
+
+    // expect(result.current.query.data).equals({
+    //   name: 'instance_name',
+    //   auth: {
+    //     method: 'external',
+    //   }
+    // });
+  });
+});
+
+describe("instance admin api interaction with listing", () => {
+  it("should evict cache when creating a new instance", async () => {
+    const env = new ApiMockEnvironment();
+
+    env.addRequestExpectation(API_LIST_INSTANCES, {
+      response: {
+        instances: [
+          {
+            name: "instance_name",
+          } as MerchantBackend.Instances.Instance,
+        ],
+      },
+    });
+
+    const hookBehavior = await tests.hookBehaveLikeThis(
+      () => {
+        const api = useAdminAPI();
+        const query = useBackendInstances();
+        return { query, api };
+      },
+      {},
+      [
+        ({ query, api }) => {
+          expect(query.loading).true;
+        },
+        ({ query, api }) => {
+          expect(env.assertJustExpectedRequestWereMade()).deep.eq({
+            result: "ok",
+          });
+          expect(query.loading).false;
+          expect(query.ok).true;
+          if (!query.ok) return;
+          expect(query.data).deep.equals({
+            instances: [
+              {
+                name: "instance_name",
+              },
+            ],
+          });
+
+          env.addRequestExpectation(API_CREATE_INSTANCE, {
+            request: {
+              name: "other_name",
+            } as MerchantBackend.Instances.InstanceConfigurationMessage,
+          });
+          env.addRequestExpectation(API_LIST_INSTANCES, {
+            response: {
+              instances: [
+                {
+                  name: "instance_name",
+                } as MerchantBackend.Instances.Instance,
+                {
+                  name: "other_name",
+                } as MerchantBackend.Instances.Instance,
+              ],
+            },
+          });
+
+          api.createInstance({
+            name: "other_name",
+          } as MerchantBackend.Instances.InstanceConfigurationMessage);
+        },
+        ({ query, api }) => {
+          expect(env.assertJustExpectedRequestWereMade()).deep.eq({
+            result: "ok",
+          });
+          expect(query.loading).false;
+          expect(query.ok).true;
+          if (!query.ok) return;
+          expect(query.data).deep.equals({
+            instances: [
+              {
+                name: "instance_name",
+              },
+              {
+                name: "other_name",
+              },
+            ],
+          });
+        },
+      ],
+      env.buildTestingContext(),
+    );
+    expect(hookBehavior).deep.eq({ result: "ok" });
+    expect(env.assertJustExpectedRequestWereMade()).deep.eq({ result: "ok" });
+  });
+
+  it("should evict cache when deleting an instance", async () => {
+    const env = new ApiMockEnvironment();
+
+    env.addRequestExpectation(API_LIST_INSTANCES, {
+      response: {
+        instances: [
+          {
+            id: "default",
+            name: "instance_name",
+          } as MerchantBackend.Instances.Instance,
+          {
+            id: "the_id",
+            name: "second_instance",
+          } as MerchantBackend.Instances.Instance,
+        ],
+      },
+    });
+
+    const hookBehavior = await tests.hookBehaveLikeThis(
+      () => {
+        const api = useAdminAPI();
+        const query = useBackendInstances();
+        return { query, api };
+      },
+      {},
+      [
+        ({ query, api }) => {
+          expect(query.loading).true;
+        },
+        ({ query, api }) => {
+          expect(env.assertJustExpectedRequestWereMade()).deep.eq({
+            result: "ok",
+          });
+          expect(query.loading).false;
+          expect(query.ok).true;
+          if (!query.ok) return;
+          expect(query.data).deep.equals({
+            instances: [
+              {
+                id: "default",
+                name: "instance_name",
+              },
+              {
+                id: "the_id",
+                name: "second_instance",
+              },
+            ],
+          });
+
+          env.addRequestExpectation(API_DELETE_INSTANCE("the_id"), {});
+          env.addRequestExpectation(API_LIST_INSTANCES, {
+            response: {
+              instances: [
+                {
+                  id: "default",
+                  name: "instance_name",
+                } as MerchantBackend.Instances.Instance,
+              ],
+            },
+          });
+
+          api.deleteInstance("the_id");
+        },
+        ({ query, api }) => {
+          expect(env.assertJustExpectedRequestWereMade()).deep.eq({
+            result: "ok",
+          });
+          expect(query.loading).false;
+          expect(query.ok).true;
+          if (!query.ok) return;
+          expect(query.data).deep.equals({
+            instances: [
+              {
+                id: "default",
+                name: "instance_name",
+              },
+            ],
+          });
+        },
+      ],
+      env.buildTestingContext(),
+    );
+    expect(hookBehavior).deep.eq({ result: "ok" });
+    expect(env.assertJustExpectedRequestWereMade()).deep.eq({ result: "ok" });
+
+    // const { result, waitForNextUpdate } = renderHook(
+    //   () => {
+    //     const api = useAdminAPI();
+    //     const query = useBackendInstances();
+
+    //     return { query, api };
+    //   },
+    //   { wrapper: TestingContext }
+    // );
+
+    // expect(result.current).not.undefined;
+    // if (!result.current) {
+    //   return;
+    // }
+    // expect(result.current.query.loading).true;
+
+    // await waitForNextUpdate({ timeout: 1 });
+
+    // expect(env.assertJustExpectedRequestWereMade()).deep.eq({ result: "ok" 
});
+
+    // expect(result.current.query.loading).false;
+
+    // expect(result.current?.query.ok).true;
+    // if (!result.current?.query.ok) return;
+
+    // expect(result.current.query.data).equals({
+    //   instances: [{
+    //     id: 'default',
+    //     name: 'instance_name'
+    //   }, {
+    //     id: 'the_id',
+    //     name: 'second_instance'
+    //   }]
+    // });
+
+    // env.addRequestExpectation(API_DELETE_INSTANCE('the_id'), {});
+
+    // act(async () => {
+    //   await result.current?.api.deleteInstance('the_id');
+    // });
+
+    // expect(env.assertJustExpectedRequestWereMade()).deep.eq({ result: "ok" 
});
+
+    // env.addRequestExpectation(API_LIST_INSTANCES, {
+    //   response: {
+    //     instances: [{
+    //       id: 'default',
+    //       name: 'instance_name'
+    //     } as MerchantBackend.Instances.Instance]
+    //   },
+    // });
+
+    // expect(result.current.query.loading).false;
+
+    // await waitForNextUpdate({ timeout: 1 });
+
+    // expect(env.assertJustExpectedRequestWereMade()).deep.eq({ result: "ok" 
});
+
+    // expect(result.current.query.loading).false;
+    // expect(result.current.query.ok).true;
+
+    // expect(result.current.query.data).equals({
+    //   instances: [{
+    //     id: 'default',
+    //     name: 'instance_name'
+    //   }]
+    // });
+  });
+
+  it("should evict cache when deleting (purge) an instance", async () => {
+    const env = new ApiMockEnvironment();
+
+    env.addRequestExpectation(API_LIST_INSTANCES, {
+      response: {
+        instances: [
+          {
+            id: "default",
+            name: "instance_name",
+          } as MerchantBackend.Instances.Instance,
+          {
+            id: "the_id",
+            name: "second_instance",
+          } as MerchantBackend.Instances.Instance,
+        ],
+      },
+    });
+
+    const hookBehavior = await tests.hookBehaveLikeThis(
+      () => {
+        const api = useAdminAPI();
+        const query = useBackendInstances();
+        return { query, api };
+      },
+      {},
+      [
+        ({ query, api }) => {
+          expect(query.loading).true;
+        },
+        ({ query, api }) => {
+          expect(env.assertJustExpectedRequestWereMade()).deep.eq({
+            result: "ok",
+          });
+          expect(query.loading).false;
+          expect(query.ok).true;
+          if (!query.ok) return;
+          expect(query.data).deep.equals({
+            instances: [
+              {
+                id: "default",
+                name: "instance_name",
+              },
+              {
+                id: "the_id",
+                name: "second_instance",
+              },
+            ],
+          });
+
+          env.addRequestExpectation(API_DELETE_INSTANCE("the_id"), {
+            qparam: {
+              purge: "YES",
+            },
+          });
+          env.addRequestExpectation(API_LIST_INSTANCES, {
+            response: {
+              instances: [
+                {
+                  id: "default",
+                  name: "instance_name",
+                } as MerchantBackend.Instances.Instance,
+              ],
+            },
+          });
+
+          api.purgeInstance("the_id");
+        },
+        ({ query, api }) => {
+          expect(env.assertJustExpectedRequestWereMade()).deep.eq({
+            result: "ok",
+          });
+          expect(query.loading).false;
+          expect(query.ok).true;
+          if (!query.ok) return;
+          expect(query.data).deep.equals({
+            instances: [
+              {
+                id: "default",
+                name: "instance_name",
+              },
+            ],
+          });
+        },
+      ],
+      env.buildTestingContext(),
+    );
+    expect(hookBehavior).deep.eq({ result: "ok" });
+    expect(env.assertJustExpectedRequestWereMade()).deep.eq({ result: "ok" });
+  });
+});
+
+describe("instance management api interaction with listing", () => {
+  it("should evict cache when updating an instance", async () => {
+    const env = new ApiMockEnvironment();
+
+    env.addRequestExpectation(API_LIST_INSTANCES, {
+      response: {
+        instances: [
+          {
+            id: "managed",
+            name: "instance_name",
+          } as MerchantBackend.Instances.Instance,
+        ],
+      },
+    });
+
+    const hookBehavior = await tests.hookBehaveLikeThis(
+      () => {
+        const api = useManagementAPI("managed");
+        const query = useBackendInstances();
+        return { query, api };
+      },
+      {},
+      [
+        ({ query, api }) => {
+          expect(query.loading).true;
+        },
+        ({ query, api }) => {
+          expect(env.assertJustExpectedRequestWereMade()).deep.eq({
+            result: "ok",
+          });
+          expect(query.loading).false;
+          expect(query.ok).true;
+          if (!query.ok) return;
+          expect(query.data).deep.equals({
+            instances: [
+              {
+                id: "managed",
+                name: "instance_name",
+              },
+            ],
+          });
+
+          env.addRequestExpectation(API_UPDATE_INSTANCE_BY_ID("managed"), {
+            request: {
+              name: "other_name",
+            } as MerchantBackend.Instances.InstanceReconfigurationMessage,
+          });
+          env.addRequestExpectation(API_LIST_INSTANCES, {
+            response: {
+              instances: [
+                {
+                  id: "managed",
+                  name: "other_name",
+                } as MerchantBackend.Instances.Instance,
+              ],
+            },
+          });
+
+          api.updateInstance({
+            name: "other_name",
+          } as MerchantBackend.Instances.InstanceConfigurationMessage);
+        },
+        ({ query, api }) => {
+          expect(env.assertJustExpectedRequestWereMade()).deep.eq({
+            result: "ok",
+          });
+          expect(query.loading).false;
+          expect(query.ok).true;
+          if (!query.ok) return;
+          expect(query.data).deep.equals({
+            instances: [
+              {
+                id: "managed",
+                name: "other_name",
+              },
+            ],
+          });
+        },
+      ],
+      env.buildTestingContext(),
+    );
+    expect(hookBehavior).deep.eq({ result: "ok" });
+    expect(env.assertJustExpectedRequestWereMade()).deep.eq({ result: "ok" });
+  });
+});
diff --git a/packages/auditor-backoffice-ui/src/hooks/instance.ts 
b/packages/auditor-backoffice-ui/src/hooks/instance.ts
new file mode 100644
index 000000000..0677191db
--- /dev/null
+++ b/packages/auditor-backoffice-ui/src/hooks/instance.ts
@@ -0,0 +1,313 @@
+/*
+ This file is part of GNU Taler
+ (C) 2021-2023 Taler Systems S.A.
+
+ GNU Taler is free software; you can redistribute it and/or modify it under the
+ terms of the GNU General Public License as published by the Free Software
+ Foundation; either version 3, or (at your option) any later version.
+
+ GNU Taler is distributed in the hope that it will be useful, but WITHOUT ANY
+ WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
+ A PARTICULAR PURPOSE.  See the GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License along with
+ GNU Taler; see the file COPYING.  If not, see <http://www.gnu.org/licenses/>
+ */
+import {
+  HttpResponse,
+  HttpResponseOk,
+  RequestError,
+} from "@gnu-taler/web-util/browser";
+import { useBackendContext } from "../context/backend.js";
+import { AccessToken, MerchantBackend } from "../declaration.js";
+import {
+  useBackendBaseRequest,
+  useBackendInstanceRequest,
+  useCredentialsChecker,
+  useMatchMutate,
+} from "./backend.js";
+
+// FIX default import https://github.com/microsoft/TypeScript/issues/49189
+import _useSWR, { SWRHook, useSWRConfig } from "swr";
+const useSWR = _useSWR as unknown as SWRHook;
+
+interface InstanceAPI {
+  updateInstance: (
+    data: MerchantBackend.Instances.InstanceReconfigurationMessage,
+  ) => Promise<void>;
+  deleteInstance: () => Promise<void>;
+  clearAccessToken: (currentToken: AccessToken | undefined) => Promise<void>;
+  setNewAccessToken: (currentToken: AccessToken | undefined, token: 
AccessToken) => Promise<void>;
+}
+
+export function useAdminAPI(): AdminAPI {
+  const { request } = useBackendBaseRequest();
+  const mutateAll = useMatchMutate();
+
+  const createInstance = async (
+    instance: MerchantBackend.Instances.InstanceConfigurationMessage,
+  ): Promise<void> => {
+    await request(`/management/instances`, {
+      method: "POST",
+      data: instance,
+    });
+
+    mutateAll(/\/management\/instances/);
+  };
+
+  const deleteInstance = async (id: string): Promise<void> => {
+    await request(`/management/instances/${id}`, {
+      method: "DELETE",
+    });
+
+    mutateAll(/\/management\/instances/);
+  };
+
+  const purgeInstance = async (id: string): Promise<void> => {
+    await request(`/management/instances/${id}`, {
+      method: "DELETE",
+      params: {
+        purge: "YES",
+      },
+    });
+
+    mutateAll(/\/management\/instances/);
+  };
+
+  return { createInstance, deleteInstance, purgeInstance };
+}
+
+export interface AdminAPI {
+  createInstance: (
+    data: MerchantBackend.Instances.InstanceConfigurationMessage,
+  ) => Promise<void>;
+  deleteInstance: (id: string) => Promise<void>;
+  purgeInstance: (id: string) => Promise<void>;
+}
+
+export function useManagementAPI(instanceId: string): InstanceAPI {
+  const mutateAll = useMatchMutate();
+  const { url: backendURL } = useBackendContext()
+  const { updateToken } = useBackendContext();
+  const { request } = useBackendBaseRequest();
+  const { requestNewLoginToken } = useCredentialsChecker()
+
+  const updateInstance = async (
+    instance: MerchantBackend.Instances.InstanceReconfigurationMessage,
+  ): Promise<void> => {
+    await request(`/management/instances/${instanceId}`, {
+      method: "PATCH",
+      data: instance,
+    });
+
+    mutateAll(/\/management\/instances/);
+  };
+
+  const deleteInstance = async (): Promise<void> => {
+    await request(`/management/instances/${instanceId}`, {
+      method: "DELETE",
+    });
+
+    mutateAll(/\/management\/instances/);
+  };
+
+  const clearAccessToken = async (currentToken: AccessToken | undefined): 
Promise<void> => {
+    await request(`/management/instances/${instanceId}/auth`, {
+      method: "POST",
+      token: currentToken,
+      data: { method: "external" },
+    });
+
+    mutateAll(/\/management\/instances/);
+  };
+
+  const setNewAccessToken = async (currentToken: AccessToken | undefined, 
newToken: AccessToken): Promise<void> => {
+    await request(`/management/instances/${instanceId}/auth`, {
+      method: "POST",
+      token: currentToken,
+      data: { method: "token", token: newToken },
+    });
+
+    const resp = await requestNewLoginToken(backendURL, newToken)
+    if (resp.valid) {
+      const { token, expiration } = resp
+      updateToken({ token, expiration });
+    } else {
+      updateToken(undefined)
+    }
+
+    mutateAll(/\/management\/instances/);
+  };
+
+  return { updateInstance, deleteInstance, setNewAccessToken, clearAccessToken 
};
+}
+
+export function useInstanceAPI(): InstanceAPI {
+  const { mutate } = useSWRConfig();
+  const { url: backendURL, updateToken } = useBackendContext()
+
+  const {
+    token: adminToken,
+  } = useBackendContext();
+  const { request } = useBackendInstanceRequest();
+  const { requestNewLoginToken } = useCredentialsChecker()
+
+  const updateInstance = async (
+    instance: MerchantBackend.Instances.InstanceReconfigurationMessage,
+  ): Promise<void> => {
+    await request(`/private/`, {
+      method: "PATCH",
+      data: instance,
+    });
+
+    if (adminToken) mutate(["/private/instances", adminToken, backendURL], 
null);
+    mutate([`/private/`], null);
+  };
+
+  const deleteInstance = async (): Promise<void> => {
+    await request(`/private/`, {
+      method: "DELETE",
+      // token: adminToken,
+    });
+
+    if (adminToken) mutate(["/private/instances", adminToken, backendURL], 
null);
+    mutate([`/private/`], null);
+  };
+
+  const clearAccessToken = async (currentToken: AccessToken | undefined): 
Promise<void> => {
+    await request(`/private/auth`, {
+      method: "POST",
+      token: currentToken,
+      data: { method: "external" },
+    });
+
+    mutate([`/private/`], null);
+  };
+
+  const setNewAccessToken = async (currentToken: AccessToken | undefined, 
newToken: AccessToken): Promise<void> => {
+    await request(`/private/auth`, {
+      method: "POST",
+      token: currentToken,
+      data: { method: "token", token: newToken },
+    });
+
+    const resp = await requestNewLoginToken(backendURL, newToken)
+    if (resp.valid) {
+      const { token, expiration } = resp
+      updateToken({ token, expiration });
+    } else {
+      updateToken(undefined)
+    }
+
+    mutate([`/private/`], null);
+  };
+
+  return { updateInstance, deleteInstance, setNewAccessToken, clearAccessToken 
};
+}
+
+export function useInstanceDetails(): HttpResponse<
+  MerchantBackend.Instances.QueryInstancesResponse,
+  MerchantBackend.ErrorDetail
+> {
+  const { fetcher } = useBackendInstanceRequest();
+
+  const { data, error, isValidating } = useSWR<
+    HttpResponseOk<MerchantBackend.Instances.QueryInstancesResponse>,
+    RequestError<MerchantBackend.ErrorDetail>
+  >([`/private/`], fetcher, {
+    refreshInterval: 0,
+    refreshWhenHidden: false,
+    revalidateOnFocus: false,
+    revalidateOnReconnect: false,
+    refreshWhenOffline: false,
+    revalidateIfStale: false,
+    errorRetryCount: 0,
+    errorRetryInterval: 1,
+    shouldRetryOnError: false,
+  });
+
+  if (isValidating) return { loading: true, data: data?.data };
+  if (data) return data;
+  if (error) return error.cause;
+  return { loading: true };
+}
+
+type KYCStatus =
+  | { type: "ok" }
+  | { type: "redirect"; status: MerchantBackend.KYC.AccountKycRedirects };
+
+export function useInstanceKYCDetails(): HttpResponse<
+  KYCStatus,
+  MerchantBackend.ErrorDetail
+> {
+  const { fetcher } = useBackendInstanceRequest();
+
+  const { data, error } = useSWR<
+    HttpResponseOk<MerchantBackend.KYC.AccountKycRedirects>,
+    RequestError<MerchantBackend.ErrorDetail>
+  >([`/private/kyc`], fetcher, {
+    refreshInterval: 60 * 1000,
+    refreshWhenHidden: false,
+    revalidateOnFocus: false,
+    revalidateIfStale: false,
+    revalidateOnMount: false,
+    revalidateOnReconnect: false,
+    refreshWhenOffline: false,
+    errorRetryCount: 0,
+    errorRetryInterval: 1,
+    shouldRetryOnError: false,
+  });
+
+  if (data) {
+    if (data.info?.status === 202)
+      return { ok: true, data: { type: "redirect", status: data.data } };
+    return { ok: true, data: { type: "ok" } };
+  }
+  if (error) return error.cause;
+  return { loading: true };
+}
+
+export function useManagedInstanceDetails(
+  instanceId: string,
+): HttpResponse<
+  MerchantBackend.Instances.QueryInstancesResponse,
+  MerchantBackend.ErrorDetail
+> {
+  const { request } = useBackendBaseRequest();
+
+  const { data, error, isValidating } = useSWR<
+    HttpResponseOk<MerchantBackend.Instances.QueryInstancesResponse>,
+    RequestError<MerchantBackend.ErrorDetail>
+  >([`/management/instances/${instanceId}`], request, {
+    refreshInterval: 0,
+    refreshWhenHidden: false,
+    revalidateOnFocus: false,
+    revalidateOnReconnect: false,
+    refreshWhenOffline: false,
+    errorRetryCount: 0,
+    errorRetryInterval: 1,
+    shouldRetryOnError: false,
+  });
+
+  if (isValidating) return { loading: true, data: data?.data };
+  if (data) return data;
+  if (error) return error.cause;
+  return { loading: true };
+}
+
+export function useBackendInstances(): HttpResponse<
+  MerchantBackend.Instances.InstancesResponse,
+  MerchantBackend.ErrorDetail
+> {
+  const { request } = useBackendBaseRequest();
+
+  const { data, error, isValidating } = useSWR<
+    HttpResponseOk<MerchantBackend.Instances.InstancesResponse>,
+    RequestError<MerchantBackend.ErrorDetail>
+  >(["/management/instances"], request);
+
+  if (isValidating) return { loading: true, data: data?.data };
+  if (data) return data;
+  if (error) return error.cause;
+  return { loading: true };
+}
diff --git a/packages/auditor-backoffice-ui/src/hooks/listener.ts 
b/packages/auditor-backoffice-ui/src/hooks/listener.ts
new file mode 100644
index 000000000..d101f7bb8
--- /dev/null
+++ b/packages/auditor-backoffice-ui/src/hooks/listener.ts
@@ -0,0 +1,85 @@
+/*
+ This file is part of GNU Taler
+ (C) 2021-2023 Taler Systems S.A.
+
+ GNU Taler is free software; you can redistribute it and/or modify it under the
+ terms of the GNU General Public License as published by the Free Software
+ Foundation; either version 3, or (at your option) any later version.
+
+ GNU Taler is distributed in the hope that it will be useful, but WITHOUT ANY
+ WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
+ A PARTICULAR PURPOSE.  See the GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License along with
+ GNU Taler; see the file COPYING.  If not, see <http://www.gnu.org/licenses/>
+ */
+
+/**
+ *
+ * @author Sebastian Javier Marchano (sebasjm)
+ */
+
+import { useState } from "preact/hooks";
+
+/**
+ * This component is used when a component wants one child to have a trigger 
for
+ * an action (a button) and other child have the action implemented (like
+ * gathering information with a form). The difference with other approaches is
+ * that in this case the parent component is not holding the state.
+ *
+ * It will return a subscriber and activator.
+ *
+ * The activator may be undefined, if it is undefined it is indicating that the
+ * subscriber is not ready to be called.
+ *
+ * The subscriber will receive a function (the listener) that will be call 
when the
+ * activator runs. The listener must return the collected information.
+ *
+ * As a result, when the activator is triggered by a child component, the
+ * @action function is called receives the information from the listener 
defined by other
+ * child component
+ *
+ * @param action from <T> to <R>
+ * @returns activator and subscriber, undefined activator means that there is 
not subscriber
+ */
+
+export function useListener<T, R = any>(
+  action: (r: T) => Promise<R>,
+): [undefined | (() => Promise<R>), (listener?: () => T) => void] {
+  type RunnerHandler = { toBeRan?: () => Promise<R> };
+  const [state, setState] = useState<RunnerHandler>({});
+
+  /**
+   * subscriber will receive a method that will be call when the activator runs
+   *
+   * @param listener function to be run when the activator runs
+   */
+  const subscriber = (listener?: () => T) => {
+    if (listener) {
+      setState({
+        toBeRan: () => {
+          const whatWeGetFromTheListener = listener();
+          return action(whatWeGetFromTheListener);
+        },
+      });
+    } else {
+      setState({
+        toBeRan: undefined,
+      });
+    }
+  };
+
+  /**
+   * activator will call runner if there is someone subscribed
+   */
+  const activator = state.toBeRan
+    ? async () => {
+        if (state.toBeRan) {
+          return state.toBeRan();
+        }
+        return Promise.reject();
+      }
+    : undefined;
+
+  return [activator, subscriber];
+}
diff --git a/packages/auditor-backoffice-ui/src/hooks/notifications.ts 
b/packages/auditor-backoffice-ui/src/hooks/notifications.ts
new file mode 100644
index 000000000..133ddd80b
--- /dev/null
+++ b/packages/auditor-backoffice-ui/src/hooks/notifications.ts
@@ -0,0 +1,56 @@
+/*
+ This file is part of GNU Taler
+ (C) 2021-2023 Taler Systems S.A.
+
+ GNU Taler is free software; you can redistribute it and/or modify it under the
+ terms of the GNU General Public License as published by the Free Software
+ Foundation; either version 3, or (at your option) any later version.
+
+ GNU Taler is distributed in the hope that it will be useful, but WITHOUT ANY
+ WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
+ A PARTICULAR PURPOSE.  See the GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License along with
+ GNU Taler; see the file COPYING.  If not, see <http://www.gnu.org/licenses/>
+ */
+
+/**
+ *
+ * @author Sebastian Javier Marchano (sebasjm)
+ */
+
+import { useState } from "preact/hooks";
+import { Notification } from "../utils/types.js";
+
+interface Result {
+  notifications: Notification[];
+  pushNotification: (n: Notification) => void;
+  removeNotification: (n: Notification) => void;
+}
+
+type NotificationWithDate = Notification & { since: Date };
+
+export function useNotifications(
+  initial: Notification[] = [],
+  timeout = 3000,
+): Result {
+  const [notifications, setNotifications] = useState<NotificationWithDate[]>(
+    initial.map((i) => ({ ...i, since: new Date() })),
+  );
+
+  const pushNotification = (n: Notification): void => {
+    const entry = { ...n, since: new Date() };
+    setNotifications((ns) => [...ns, entry]);
+    if (n.type !== "ERROR")
+      setTimeout(() => {
+        setNotifications((ns) => ns.filter((x) => x.since !== entry.since));
+      }, timeout);
+  };
+
+  const removeNotification = (notif: Notification) => {
+    setNotifications((ns: NotificationWithDate[]) =>
+      ns.filter((n) => n !== notif),
+    );
+  };
+  return { notifications, pushNotification, removeNotification };
+}
diff --git a/packages/auditor-backoffice-ui/src/hooks/order.test.ts 
b/packages/auditor-backoffice-ui/src/hooks/order.test.ts
new file mode 100644
index 000000000..c243309a8
--- /dev/null
+++ b/packages/auditor-backoffice-ui/src/hooks/order.test.ts
@@ -0,0 +1,587 @@
+/*
+ This file is part of GNU Taler
+ (C) 2021-2023 Taler Systems S.A.
+
+ GNU Taler is free software; you can redistribute it and/or modify it under the
+ terms of the GNU General Public License as published by the Free Software
+ Foundation; either version 3, or (at your option) any later version.
+
+ GNU Taler is distributed in the hope that it will be useful, but WITHOUT ANY
+ WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
+ A PARTICULAR PURPOSE.  See the GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License along with
+ GNU Taler; see the file COPYING.  If not, see <http://www.gnu.org/licenses/>
+ */
+
+/**
+ *
+ * @author Sebastian Javier Marchano (sebasjm)
+ */
+
+import * as tests from "@gnu-taler/web-util/testing";
+import { expect } from "chai";
+import { MerchantBackend } from "../declaration.js";
+import { useInstanceOrders, useOrderAPI, useOrderDetails } from "./order.js";
+import { ApiMockEnvironment } from "./testing.js";
+import {
+  API_CREATE_ORDER,
+  API_DELETE_ORDER,
+  API_FORGET_ORDER_BY_ID,
+  API_GET_ORDER_BY_ID,
+  API_LIST_ORDERS,
+  API_REFUND_ORDER_BY_ID,
+} from "./urls.js";
+
+describe("order api interaction with listing", () => {
+  it("should evict cache when creating an order", async () => {
+    const env = new ApiMockEnvironment();
+
+    env.addRequestExpectation(API_LIST_ORDERS, {
+      qparam: { delta: -20, paid: "yes" },
+      response: {
+        orders: [{ order_id: "1" }, { order_id: "2" } as 
MerchantBackend.Orders.OrderHistoryEntry],
+      },
+    });
+
+    const newDate = (d: Date) => {
+      //console.log("new date", d);
+    };
+
+    const hookBehavior = await tests.hookBehaveLikeThis(
+      () => {
+        const query = useInstanceOrders({ paid: "yes" }, newDate);
+        const api = useOrderAPI();
+        return { query, api };
+      },
+      {},
+      [
+        ({ query, api }) => {
+          expect(query.loading).true;
+        },
+        ({ query, api }) => {
+          expect(env.assertJustExpectedRequestWereMade()).deep.eq({
+            result: "ok",
+          });
+          expect(query.loading).undefined;
+          expect(query.ok).true;
+          if (!query.ok) return;
+          expect(query.data).deep.equals({
+            orders: [{ order_id: "1" }, { order_id: "2" }],
+          });
+
+          env.addRequestExpectation(API_CREATE_ORDER, {
+            request: {
+              order: { amount: "ARS:12", summary: "pay me" },
+            },
+            response: { order_id: "3" },
+          });
+
+          env.addRequestExpectation(API_LIST_ORDERS, {
+            qparam: { delta: -20, paid: "yes" },
+            response: {
+              orders: [{ order_id: "1" }, { order_id: "2" } as any, { 
order_id: "3" } as any],
+            },
+          });
+
+          api.createOrder({
+            order: { amount: "ARS:12", summary: "pay me" },
+          } as any);
+        },
+        ({ query, api }) => {
+          expect(env.assertJustExpectedRequestWereMade()).deep.eq({
+            result: "ok",
+          });
+
+          expect(query.loading).undefined;
+          expect(query.ok).true;
+          if (!query.ok) return;
+          expect(query.data).deep.equals({
+            orders: [{ order_id: "1" }, { order_id: "2" }, { order_id: "3" }],
+          });
+        },
+      ],
+      env.buildTestingContext(),
+    );
+    expect(hookBehavior).deep.eq({ result: "ok" });
+    expect(env.assertJustExpectedRequestWereMade()).deep.eq({ result: "ok" });
+  });
+
+  it("should evict cache when doing a refund", async () => {
+    const env = new ApiMockEnvironment();
+
+    env.addRequestExpectation(API_LIST_ORDERS, {
+      qparam: { delta: -20, paid: "yes" },
+      response: { orders: [{
+        order_id: "1",
+        amount: "EUR:12",
+        refundable: true,
+      } as MerchantBackend.Orders.OrderHistoryEntry] },
+    });
+
+    const newDate = (d: Date) => {
+      //console.log("new date", d);
+    };
+
+    const hookBehavior = await tests.hookBehaveLikeThis(
+      () => {
+        const query = useInstanceOrders({ paid: "yes" }, newDate);
+        const api = useOrderAPI();
+        return { query, api };
+      },
+      {},
+      [
+        ({ query, api }) => {
+          expect(query.loading).true;
+        },
+        ({ query, api }) => {
+          expect(env.assertJustExpectedRequestWereMade()).deep.eq({
+            result: "ok",
+          });
+
+          expect(query.loading).undefined;
+          expect(query.ok).true;
+          if (!query.ok) return;
+          expect(query.data).deep.equals({
+            orders: [
+              {
+                order_id: "1",
+                amount: "EUR:12",
+                refundable: true,
+              },
+            ],
+          });
+          env.addRequestExpectation(API_REFUND_ORDER_BY_ID("1"), {
+            request: {
+              reason: "double pay",
+              refund: "EUR:1",
+            },
+          });
+
+          env.addRequestExpectation(API_LIST_ORDERS, {
+            qparam: { delta: -20, paid: "yes" },
+            response: { orders: [
+              { order_id: "1", amount: "EUR:12", refundable: false } as any,
+            ] },
+          });
+
+          api.refundOrder("1", {
+            reason: "double pay",
+            refund: "EUR:1",
+          });
+        },
+        ({ query, api }) => {
+          expect(env.assertJustExpectedRequestWereMade()).deep.eq({
+            result: "ok",
+          });
+
+          expect(query.loading).undefined;
+          expect(query.ok).true;
+          if (!query.ok) return;
+          expect(query.data).deep.equals({
+            orders: [
+              {
+                order_id: "1",
+                amount: "EUR:12",
+                refundable: false,
+              },
+            ],
+          });
+        },
+      ],
+      env.buildTestingContext(),
+    );
+
+    expect(hookBehavior).deep.eq({ result: "ok" });
+    expect(env.assertJustExpectedRequestWereMade()).deep.eq({ result: "ok" });
+  });
+
+  it("should evict cache when deleting an order", async () => {
+    const env = new ApiMockEnvironment();
+
+    env.addRequestExpectation(API_LIST_ORDERS, {
+      qparam: { delta: -20, paid: "yes" },
+      response: {
+        orders: [{ order_id: "1" }, { order_id: "2" } as 
MerchantBackend.Orders.OrderHistoryEntry],
+      },
+    });
+
+    const newDate = (d: Date) => {
+      //console.log("new date", d);
+    };
+
+    const hookBehavior = await tests.hookBehaveLikeThis(
+      () => {
+        const query = useInstanceOrders({ paid: "yes" }, newDate);
+        const api = useOrderAPI();
+        return { query, api };
+      },
+      {},
+      [
+        ({ query, api }) => {
+          expect(query.loading).true;
+        },
+        ({ query, api }) => {
+          expect(env.assertJustExpectedRequestWereMade()).deep.eq({
+            result: "ok",
+          });
+          expect(query.loading).undefined;
+          expect(query.ok).true;
+          if (!query.ok) return;
+          expect(query.data).deep.equals({
+            orders: [{ order_id: "1" }, { order_id: "2" }],
+          });
+
+          env.addRequestExpectation(API_DELETE_ORDER("1"), {});
+
+          env.addRequestExpectation(API_LIST_ORDERS, {
+            qparam: { delta: -20, paid: "yes" },
+            response: {
+              orders: [{ order_id: "2" } as any],
+            },
+          });
+
+          api.deleteOrder("1");
+        },
+        ({ query, api }) => {
+          expect(env.assertJustExpectedRequestWereMade()).deep.eq({
+            result: "ok",
+          });
+          expect(query.loading).undefined;
+          expect(query.ok).true;
+          if (!query.ok) return;
+          expect(query.data).deep.equals({
+            orders: [{ order_id: "2" }],
+          });
+        },
+      ],
+      env.buildTestingContext(),
+    );
+    expect(hookBehavior).deep.eq({ result: "ok" });
+    expect(env.assertJustExpectedRequestWereMade()).deep.eq({ result: "ok" });
+  });
+});
+
+describe("order api interaction with details", () => {
+  it("should evict cache when doing a refund", async () => {
+    const env = new ApiMockEnvironment();
+
+    env.addRequestExpectation(API_GET_ORDER_BY_ID("1"), {
+      // qparam: { delta: 0, paid: "yes" },
+      response: {
+        summary: "description",
+        refund_amount: "EUR:0",
+      } as unknown as MerchantBackend.Orders.CheckPaymentPaidResponse,
+    });
+
+    const newDate = (d: Date) => {
+      //console.log("new date", d);
+    };
+
+    const hookBehavior = await tests.hookBehaveLikeThis(
+      () => {
+        const query = useOrderDetails("1");
+        const api = useOrderAPI();
+        return { query, api };
+      },
+      {},
+      [
+        ({ query, api }) => {
+          expect(query.loading).true;
+        },
+        ({ query, api }) => {
+          expect(env.assertJustExpectedRequestWereMade()).deep.eq({
+            result: "ok",
+          });
+          expect(query.loading).false;
+          expect(query.ok).true;
+          if (!query.ok) return;
+          expect(query.data).deep.equals({
+            summary: "description",
+            refund_amount: "EUR:0",
+          });
+          env.addRequestExpectation(API_REFUND_ORDER_BY_ID("1"), {
+            request: {
+              reason: "double pay",
+              refund: "EUR:1",
+            },
+          });
+
+          env.addRequestExpectation(API_GET_ORDER_BY_ID("1"), {
+            response: {
+              summary: "description",
+              refund_amount: "EUR:1",
+            } as unknown as MerchantBackend.Orders.CheckPaymentPaidResponse,
+          });
+
+          api.refundOrder("1", {
+            reason: "double pay",
+            refund: "EUR:1",
+          });
+        },
+        ({ query, api }) => {
+          expect(env.assertJustExpectedRequestWereMade()).deep.eq({
+            result: "ok",
+          });
+          expect(query.loading).false;
+          expect(query.ok).true;
+          if (!query.ok) return;
+          expect(query.data).deep.equals({
+            summary: "description",
+            refund_amount: "EUR:1",
+          });
+        },
+      ],
+      env.buildTestingContext(),
+    );
+
+    expect(hookBehavior).deep.eq({ result: "ok" });
+    expect(env.assertJustExpectedRequestWereMade()).deep.eq({ result: "ok" });
+  });
+
+  it("should evict cache when doing a forget", async () => {
+    const env = new ApiMockEnvironment();
+
+    env.addRequestExpectation(API_GET_ORDER_BY_ID("1"), {
+      // qparam: { delta: 0, paid: "yes" },
+      response: {
+        summary: "description",
+        refund_amount: "EUR:0",
+      } as unknown as MerchantBackend.Orders.CheckPaymentPaidResponse,
+    });
+
+    const newDate = (d: Date) => {
+      //console.log("new date", d);
+    };
+
+    const hookBehavior = await tests.hookBehaveLikeThis(
+      () => {
+        const query = useOrderDetails("1");
+        const api = useOrderAPI();
+        return { query, api };
+      },
+      {},
+      [
+        ({ query, api }) => {
+          expect(query.loading).true;
+        },
+        ({ query, api }) => {
+          expect(env.assertJustExpectedRequestWereMade()).deep.eq({
+            result: "ok",
+          });
+          expect(query.loading).false;
+          expect(query.ok).true;
+          if (!query.ok) return;
+          expect(query.data).deep.equals({
+            summary: "description",
+            refund_amount: "EUR:0",
+          });
+          env.addRequestExpectation(API_FORGET_ORDER_BY_ID("1"), {
+            request: {
+              fields: ["$.summary"],
+            },
+          });
+
+          env.addRequestExpectation(API_GET_ORDER_BY_ID("1"), {
+            response: {
+              summary: undefined,
+            } as unknown as MerchantBackend.Orders.CheckPaymentPaidResponse,
+          });
+
+          api.forgetOrder("1", {
+            fields: ["$.summary"],
+          });
+        },
+        ({ query, api }) => {
+          expect(env.assertJustExpectedRequestWereMade()).deep.eq({
+            result: "ok",
+          });
+          expect(query.loading).false;
+          expect(query.ok).true;
+          if (!query.ok) return;
+          expect(query.data).deep.equals({
+            summary: undefined,
+          });
+        },
+      ],
+      env.buildTestingContext(),
+    );
+    expect(hookBehavior).deep.eq({ result: "ok" });
+    expect(env.assertJustExpectedRequestWereMade()).deep.eq({ result: "ok" });
+  });
+});
+
+describe("order listing pagination", () => {
+  it("should not load more if has reach the end", async () => {
+    const env = new ApiMockEnvironment();
+    env.addRequestExpectation(API_LIST_ORDERS, {
+      qparam: { delta: 20, wired: "yes", date_s: 12 },
+      response: {
+        orders: [{ order_id: "1" } as any],
+      },
+    });
+
+    env.addRequestExpectation(API_LIST_ORDERS, {
+      qparam: { delta: -20, wired: "yes", date_s: 13 },
+      response: {
+        orders: [{ order_id: "2" } as any],
+      },
+    });
+
+    const newDate = (d: Date) => {
+      //console.log("new date", d);
+    };
+
+    const hookBehavior = await tests.hookBehaveLikeThis(
+      () => {
+        const date = new Date(12000);
+        const query = useInstanceOrders({ wired: "yes", date }, newDate);
+        const api = useOrderAPI();
+        return { query, api };
+      },
+      {},
+      [
+        ({ query, api }) => {
+          expect(query.loading).true;
+        },
+        ({ query, api }) => {
+          expect(env.assertJustExpectedRequestWereMade()).deep.eq({
+            result: "ok",
+          });
+          expect(query.loading).undefined;
+          expect(query.ok).true;
+          if (!query.ok) return;
+          expect(query.data).deep.equals({
+            orders: [{ order_id: "1" }, { order_id: "2" }],
+          });
+          expect(query.isReachingEnd).true;
+          expect(query.isReachingStart).true;
+
+          // should not trigger new state update or query
+          query.loadMore();
+          query.loadMorePrev();
+        },
+      ],
+      env.buildTestingContext(),
+    );
+
+    expect(hookBehavior).deep.eq({ result: "ok" });
+    expect(env.assertJustExpectedRequestWereMade()).deep.eq({ result: "ok" });
+  });
+
+  it("should load more if result brings more that PAGE_SIZE", async () => {
+    const env = new ApiMockEnvironment();
+
+    const ordersFrom0to20 = Array.from({ length: 20 }).map((e, i) => ({
+      order_id: String(i),
+    }));
+    const ordersFrom20to40 = Array.from({ length: 20 }).map((e, i) => ({
+      order_id: String(i + 20),
+    }));
+    const ordersFrom20to0 = [...ordersFrom0to20].reverse();
+
+    env.addRequestExpectation(API_LIST_ORDERS, {
+      qparam: { delta: 20, wired: "yes", date_s: 12 },
+      response: {
+        orders: ordersFrom0to20,
+      },
+    });
+
+    env.addRequestExpectation(API_LIST_ORDERS, {
+      qparam: { delta: -20, wired: "yes", date_s: 13 },
+      response: {
+        orders: ordersFrom20to40,
+      },
+    });
+
+    const newDate = (d: Date) => {
+      //console.log("new date", d);
+    };
+
+    const hookBehavior = await tests.hookBehaveLikeThis(
+      () => {
+        const date = new Date(12000);
+        const query = useInstanceOrders({ wired: "yes", date }, newDate);
+        const api = useOrderAPI();
+        return { query, api };
+      },
+      {},
+      [
+        ({ query, api }) => {
+          expect(query.loading).true;
+        },
+        ({ query, api }) => {
+          expect(env.assertJustExpectedRequestWereMade()).deep.eq({
+            result: "ok",
+          });
+          expect(query.loading).undefined;
+          expect(query.ok).true;
+          if (!query.ok) return;
+          expect(query.data).deep.equals({
+            orders: [...ordersFrom20to0, ...ordersFrom20to40],
+          });
+          expect(query.isReachingEnd).false;
+          expect(query.isReachingStart).false;
+
+          env.addRequestExpectation(API_LIST_ORDERS, {
+            qparam: { delta: -40, wired: "yes", date_s: 13 },
+            response: {
+              orders: [...ordersFrom20to40, { order_id: "41" }],
+            },
+          });
+
+          query.loadMore();
+        },
+        ({ query, api }) => {
+          expect(env.assertJustExpectedRequestWereMade()).deep.eq({
+            result: "ok",
+          });
+          expect(query.loading).true;
+        },
+        ({ query, api }) => {
+          expect(query.loading).undefined;
+          expect(query.ok).true;
+          if (!query.ok) return;
+          expect(query.data).deep.equals({
+            orders: [
+              ...ordersFrom20to0,
+              ...ordersFrom20to40,
+              { order_id: "41" },
+            ],
+          });
+
+          env.addRequestExpectation(API_LIST_ORDERS, {
+            qparam: { delta: 40, wired: "yes", date_s: 12 },
+            response: {
+              orders: [...ordersFrom0to20, { order_id: "-1" }],
+            },
+          });
+
+          query.loadMorePrev();
+        },
+        ({ query, api }) => {
+          expect(env.assertJustExpectedRequestWereMade()).deep.eq({
+            result: "ok",
+          });
+          expect(query.loading).true;
+        },
+        ({ query, api }) => {
+          expect(query.loading).undefined;
+          expect(query.ok).true;
+          if (!query.ok) return;
+          expect(query.data).deep.equals({
+            orders: [
+              { order_id: "-1" },
+              ...ordersFrom20to0,
+              ...ordersFrom20to40,
+              { order_id: "41" },
+            ],
+          });
+        },
+      ],
+      env.buildTestingContext(),
+    );
+    expect(hookBehavior).deep.eq({ result: "ok" });
+    expect(env.assertJustExpectedRequestWereMade()).deep.eq({ result: "ok" });
+  });
+});
diff --git a/packages/auditor-backoffice-ui/src/hooks/order.ts 
b/packages/auditor-backoffice-ui/src/hooks/order.ts
new file mode 100644
index 000000000..e7a893f2c
--- /dev/null
+++ b/packages/auditor-backoffice-ui/src/hooks/order.ts
@@ -0,0 +1,289 @@
+/*
+ This file is part of GNU Taler
+ (C) 2021-2023 Taler Systems S.A.
+
+ GNU Taler is free software; you can redistribute it and/or modify it under the
+ terms of the GNU General Public License as published by the Free Software
+ Foundation; either version 3, or (at your option) any later version.
+
+ GNU Taler is distributed in the hope that it will be useful, but WITHOUT ANY
+ WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
+ A PARTICULAR PURPOSE.  See the GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License along with
+ GNU Taler; see the file COPYING.  If not, see <http://www.gnu.org/licenses/>
+ */
+import {
+  HttpResponse,
+  HttpResponseOk,
+  HttpResponsePaginated,
+  RequestError,
+} from "@gnu-taler/web-util/browser";
+import { useEffect, useState } from "preact/hooks";
+import { MerchantBackend } from "../declaration.js";
+import { MAX_RESULT_SIZE, PAGE_SIZE } from "../utils/constants.js";
+import { useBackendInstanceRequest, useMatchMutate } from "./backend.js";
+
+// FIX default import https://github.com/microsoft/TypeScript/issues/49189
+import _useSWR, { SWRHook } from "swr";
+const useSWR = _useSWR as unknown as SWRHook;
+
+export interface OrderAPI {
+  //FIXME: add OutOfStockResponse on 410
+  createOrder: (
+    data: MerchantBackend.Orders.PostOrderRequest,
+  ) => Promise<HttpResponseOk<MerchantBackend.Orders.PostOrderResponse>>;
+  forgetOrder: (
+    id: string,
+    data: MerchantBackend.Orders.ForgetRequest,
+  ) => Promise<HttpResponseOk<void>>;
+  refundOrder: (
+    id: string,
+    data: MerchantBackend.Orders.RefundRequest,
+  ) => Promise<HttpResponseOk<MerchantBackend.Orders.MerchantRefundResponse>>;
+  deleteOrder: (id: string) => Promise<HttpResponseOk<void>>;
+  getPaymentURL: (id: string) => Promise<HttpResponseOk<string>>;
+}
+
+type YesOrNo = "yes" | "no";
+
+export function useOrderAPI(): OrderAPI {
+  const mutateAll = useMatchMutate();
+  const { request } = useBackendInstanceRequest();
+
+  const createOrder = async (
+    data: MerchantBackend.Orders.PostOrderRequest,
+  ): Promise<HttpResponseOk<MerchantBackend.Orders.PostOrderResponse>> => {
+    const res = await request<MerchantBackend.Orders.PostOrderResponse>(
+      `/private/orders`,
+      {
+        method: "POST",
+        data,
+      },
+    );
+    await mutateAll(/.*private\/orders.*/);
+    // mutate('')
+    return res;
+  };
+  const refundOrder = async (
+    orderId: string,
+    data: MerchantBackend.Orders.RefundRequest,
+  ): Promise<HttpResponseOk<MerchantBackend.Orders.MerchantRefundResponse>> => 
{
+    mutateAll(/@"\/private\/orders"@/);
+    const res = request<MerchantBackend.Orders.MerchantRefundResponse>(
+      `/private/orders/${orderId}/refund`,
+      {
+        method: "POST",
+        data,
+      },
+    );
+
+    // order list returns refundable information, so we must evict everything
+    await mutateAll(/.*private\/orders.*/);
+    return res;
+  };
+
+  const forgetOrder = async (
+    orderId: string,
+    data: MerchantBackend.Orders.ForgetRequest,
+  ): Promise<HttpResponseOk<void>> => {
+    mutateAll(/@"\/private\/orders"@/);
+    const res = request<void>(`/private/orders/${orderId}/forget`, {
+      method: "PATCH",
+      data,
+    });
+    // we may be forgetting some fields that are pare of the listing, so we 
must evict everything
+    await mutateAll(/.*private\/orders.*/);
+    return res;
+  };
+  const deleteOrder = async (
+    orderId: string,
+  ): Promise<HttpResponseOk<void>> => {
+    mutateAll(/@"\/private\/orders"@/);
+    const res = request<void>(`/private/orders/${orderId}`, {
+      method: "DELETE",
+    });
+    await mutateAll(/.*private\/orders.*/);
+    return res;
+  };
+
+  const getPaymentURL = async (
+    orderId: string,
+  ): Promise<HttpResponseOk<string>> => {
+    return request<MerchantBackend.Orders.MerchantOrderStatusResponse>(
+      `/private/orders/${orderId}`,
+      {
+        method: "GET",
+      },
+    ).then((res) => {
+      const url =
+        res.data.order_status === "unpaid"
+          ? res.data.taler_pay_uri
+          : res.data.contract_terms.fulfillment_url;
+      const response: HttpResponseOk<string> = res as any;
+      response.data = url || "";
+      return response;
+    });
+  };
+
+  return { createOrder, forgetOrder, deleteOrder, refundOrder, getPaymentURL };
+}
+
+export function useOrderDetails(
+  oderId: string,
+): HttpResponse<
+  MerchantBackend.Orders.MerchantOrderStatusResponse,
+  MerchantBackend.ErrorDetail
+> {
+  const { fetcher } = useBackendInstanceRequest();
+
+  const { data, error, isValidating } = useSWR<
+    HttpResponseOk<MerchantBackend.Orders.MerchantOrderStatusResponse>,
+    RequestError<MerchantBackend.ErrorDetail>
+  >([`/private/orders/${oderId}`], fetcher, {
+    refreshInterval: 0,
+    refreshWhenHidden: false,
+    revalidateOnFocus: false,
+    revalidateOnReconnect: false,
+    refreshWhenOffline: false,
+  });
+
+  if (isValidating) return { loading: true, data: data?.data };
+  if (data) return data;
+  if (error) return error.cause;
+  return { loading: true };
+}
+
+export interface InstanceOrderFilter {
+  paid?: YesOrNo;
+  refunded?: YesOrNo;
+  wired?: YesOrNo;
+  date?: Date;
+}
+
+export function useInstanceOrders(
+  args?: InstanceOrderFilter,
+  updateFilter?: (d: Date) => void,
+): HttpResponsePaginated<
+  MerchantBackend.Orders.OrderHistory,
+  MerchantBackend.ErrorDetail
+> {
+  const { orderFetcher } = useBackendInstanceRequest();
+
+  const [pageBefore, setPageBefore] = useState(1);
+  const [pageAfter, setPageAfter] = useState(1);
+
+  const totalAfter = pageAfter * PAGE_SIZE;
+  const totalBefore = args?.date ? pageBefore * PAGE_SIZE : 0;
+
+  /**
+   * FIXME: this can be cleaned up a little
+   *
+   * the logic of double query should be inside the orderFetch so from the 
hook perspective and cache
+   * is just one query and one error status
+   */
+  const {
+    data: beforeData,
+    error: beforeError,
+    isValidating: loadingBefore,
+  } = useSWR<
+    HttpResponseOk<MerchantBackend.Orders.OrderHistory>,
+    RequestError<MerchantBackend.ErrorDetail>
+  >(
+    [
+      `/private/orders`,
+      args?.paid,
+      args?.refunded,
+      args?.wired,
+      args?.date,
+      totalBefore,
+    ],
+    orderFetcher,
+  );
+  const {
+    data: afterData,
+    error: afterError,
+    isValidating: loadingAfter,
+  } = useSWR<
+    HttpResponseOk<MerchantBackend.Orders.OrderHistory>,
+    RequestError<MerchantBackend.ErrorDetail>
+  >(
+    [
+      `/private/orders`,
+      args?.paid,
+      args?.refunded,
+      args?.wired,
+      args?.date,
+      -totalAfter,
+    ],
+    orderFetcher,
+  );
+
+  //this will save last result
+  const [lastBefore, setLastBefore] = useState<
+    HttpResponse<
+      MerchantBackend.Orders.OrderHistory,
+      MerchantBackend.ErrorDetail
+    >
+  >({ loading: true });
+  const [lastAfter, setLastAfter] = useState<
+    HttpResponse<
+      MerchantBackend.Orders.OrderHistory,
+      MerchantBackend.ErrorDetail
+    >
+  >({ loading: true });
+  useEffect(() => {
+    if (afterData) setLastAfter(afterData);
+    if (beforeData) setLastBefore(beforeData);
+  }, [afterData, beforeData]);
+
+  if (beforeError) return beforeError.cause;
+  if (afterError) return afterError.cause;
+
+  // if the query returns less that we ask, then we have reach the end or 
beginning
+  const isReachingEnd = afterData && afterData.data.orders.length < totalAfter;
+  const isReachingStart =
+    args?.date === undefined ||
+    (beforeData && beforeData.data.orders.length < totalBefore);
+
+  const pagination = {
+    isReachingEnd,
+    isReachingStart,
+    loadMore: () => {
+      if (!afterData || isReachingEnd) return;
+      if (afterData.data.orders.length < MAX_RESULT_SIZE) {
+        setPageAfter(pageAfter + 1);
+      } else {
+        const from =
+          afterData.data.orders[afterData.data.orders.length - 
1].timestamp.t_s;
+        if (from && from !== "never" && updateFilter)
+          updateFilter(new Date(from * 1000));
+      }
+    },
+    loadMorePrev: () => {
+      if (!beforeData || isReachingStart) return;
+      if (beforeData.data.orders.length < MAX_RESULT_SIZE) {
+        setPageBefore(pageBefore + 1);
+      } else if (beforeData) {
+        const from =
+          beforeData.data.orders[beforeData.data.orders.length - 1].timestamp
+            .t_s;
+        if (from && from !== "never" && updateFilter)
+          updateFilter(new Date(from * 1000));
+      }
+    },
+  };
+
+  const orders =
+    !beforeData || !afterData
+      ? []
+      : (beforeData || lastBefore).data.orders
+          .slice()
+          .reverse()
+          .concat((afterData || lastAfter).data.orders);
+  if (loadingAfter || loadingBefore) return { loading: true, data: { orders } 
};
+  if (beforeData && afterData) {
+    return { ok: true, data: { orders }, ...pagination };
+  }
+  return { loading: true };
+}
diff --git a/packages/auditor-backoffice-ui/src/hooks/otp.ts 
b/packages/auditor-backoffice-ui/src/hooks/otp.ts
new file mode 100644
index 000000000..b045e365a
--- /dev/null
+++ b/packages/auditor-backoffice-ui/src/hooks/otp.ts
@@ -0,0 +1,223 @@
+/*
+ This file is part of GNU Taler
+ (C) 2021-2023 Taler Systems S.A.
+
+ GNU Taler is free software; you can redistribute it and/or modify it under the
+ terms of the GNU General Public License as published by the Free Software
+ Foundation; either version 3, or (at your option) any later version.
+
+ GNU Taler is distributed in the hope that it will be useful, but WITHOUT ANY
+ WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
+ A PARTICULAR PURPOSE.  See the GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License along with
+ GNU Taler; see the file COPYING.  If not, see <http://www.gnu.org/licenses/>
+ */
+import {
+  HttpResponse,
+  HttpResponseOk,
+  HttpResponsePaginated,
+  RequestError,
+} from "@gnu-taler/web-util/browser";
+import { useEffect, useState } from "preact/hooks";
+import { MerchantBackend } from "../declaration.js";
+import { MAX_RESULT_SIZE, PAGE_SIZE } from "../utils/constants.js";
+import { useBackendInstanceRequest, useMatchMutate } from "./backend.js";
+
+// FIX default import https://github.com/microsoft/TypeScript/issues/49189
+import _useSWR, { SWRHook } from "swr";
+const useSWR = _useSWR as unknown as SWRHook;
+
+const MOCKED_DEVICES: Record<string, MerchantBackend.OTP.OtpDeviceAddDetails> 
= {
+  "1": {
+    otp_device_description: "first device",
+    otp_algorithm: 1,
+    otp_device_id: "1",
+    otp_key: "123",
+  },
+  "2": {
+    otp_device_description: "second device",
+    otp_algorithm: 0,
+    otp_device_id: "2",
+    otp_key: "456",
+  }
+}
+
+export function useOtpDeviceAPI(): OtpDeviceAPI {
+  const mutateAll = useMatchMutate();
+  const { request } = useBackendInstanceRequest();
+
+  const createOtpDevice = async (
+    data: MerchantBackend.OTP.OtpDeviceAddDetails,
+  ): Promise<HttpResponseOk<void>> => {
+    // MOCKED_DEVICES[data.otp_device_id] = data
+    // return Promise.resolve({ ok: true, data: undefined });
+    const res = await request<void>(`/private/otp-devices`, {
+      method: "POST",
+      data,
+    });
+    await mutateAll(/.*private\/otp-devices.*/);
+    return res;
+  };
+
+  const updateOtpDevice = async (
+    deviceId: string,
+    data: MerchantBackend.OTP.OtpDevicePatchDetails,
+  ): Promise<HttpResponseOk<void>> => {
+    // MOCKED_DEVICES[deviceId].otp_algorithm = data.otp_algorithm
+    // MOCKED_DEVICES[deviceId].otp_ctr = data.otp_ctr
+    // MOCKED_DEVICES[deviceId].otp_device_description = 
data.otp_device_description
+    // MOCKED_DEVICES[deviceId].otp_key = data.otp_key
+    // return Promise.resolve({ ok: true, data: undefined });
+    const res = await request<void>(`/private/otp-devices/${deviceId}`, {
+      method: "PATCH",
+      data,
+    });
+    await mutateAll(/.*private\/otp-devices.*/);
+    return res;
+  };
+
+  const deleteOtpDevice = async (
+    deviceId: string,
+  ): Promise<HttpResponseOk<void>> => {
+    // delete MOCKED_DEVICES[deviceId]
+    // return Promise.resolve({ ok: true, data: undefined });
+    const res = await request<void>(`/private/otp-devices/${deviceId}`, {
+      method: "DELETE",
+    });
+    await mutateAll(/.*private\/otp-devices.*/);
+    return res;
+  };
+
+  return {
+    createOtpDevice,
+    updateOtpDevice,
+    deleteOtpDevice,
+  };
+}
+
+export interface OtpDeviceAPI {
+  createOtpDevice: (
+    data: MerchantBackend.OTP.OtpDeviceAddDetails,
+  ) => Promise<HttpResponseOk<void>>;
+  updateOtpDevice: (
+    id: string,
+    data: MerchantBackend.OTP.OtpDevicePatchDetails,
+  ) => Promise<HttpResponseOk<void>>;
+  deleteOtpDevice: (id: string) => Promise<HttpResponseOk<void>>;
+}
+
+export interface InstanceOtpDeviceFilter {
+}
+
+export function useInstanceOtpDevices(
+  args?: InstanceOtpDeviceFilter,
+  updatePosition?: (id: string) => void,
+): HttpResponsePaginated<
+  MerchantBackend.OTP.OtpDeviceSummaryResponse,
+  MerchantBackend.ErrorDetail
+> {
+  // return {
+  //   ok: true,
+  //   loadMore: () => { },
+  //   loadMorePrev: () => { },
+  //   data: {
+  //     otp_devices: Object.values(MOCKED_DEVICES).map(d => ({
+  //       device_description: d.otp_device_description,
+  //       otp_device_id: d.otp_device_id
+  //     }))
+  //   }
+  // }
+
+  const { fetcher } = useBackendInstanceRequest();
+
+  const [pageAfter, setPageAfter] = useState(1);
+
+  const totalAfter = pageAfter * PAGE_SIZE;
+  const {
+    data: afterData,
+    error: afterError,
+    isValidating: loadingAfter,
+  } = useSWR<
+    HttpResponseOk<MerchantBackend.OTP.OtpDeviceSummaryResponse>,
+    RequestError<MerchantBackend.ErrorDetail>
+  >([`/private/otp-devices`], fetcher);
+
+  const [lastAfter, setLastAfter] = useState<
+    HttpResponse<
+      MerchantBackend.OTP.OtpDeviceSummaryResponse,
+      MerchantBackend.ErrorDetail
+    >
+  >({ loading: true });
+  useEffect(() => {
+    if (afterData) setLastAfter(afterData);
+  }, [afterData /*, beforeData*/]);
+
+  if (afterError) return afterError.cause;
+
+  // if the query returns less that we ask, then we have reach the end or 
beginning
+  const isReachingEnd =
+    afterData && afterData.data.otp_devices.length < totalAfter;
+  const isReachingStart = true;
+
+  const pagination = {
+    isReachingEnd,
+    isReachingStart,
+    loadMore: () => {
+      if (!afterData || isReachingEnd) return;
+      if (afterData.data.otp_devices.length < MAX_RESULT_SIZE) {
+        setPageAfter(pageAfter + 1);
+      } else {
+        const from = 
`${afterData.data.otp_devices[afterData.data.otp_devices.length - 1]
+          .otp_device_id
+          }`;
+        if (from && updatePosition) updatePosition(from);
+      }
+    },
+    loadMorePrev: () => {
+    },
+  };
+
+  const otp_devices = !afterData ? [] : (afterData || 
lastAfter).data.otp_devices;
+  if (loadingAfter /* || loadingBefore */)
+    return { loading: true, data: { otp_devices } };
+  if (/*beforeData &&*/ afterData) {
+    return { ok: true, data: { otp_devices }, ...pagination };
+  }
+  return { loading: true };
+}
+
+export function useOtpDeviceDetails(
+  deviceId: string,
+): HttpResponse<
+  MerchantBackend.OTP.OtpDeviceDetails,
+  MerchantBackend.ErrorDetail
+> {
+  // return {
+  //   ok: true,
+  //   data: {
+  //     device_description: MOCKED_DEVICES[deviceId].otp_device_description,
+  //     otp_algorithm: MOCKED_DEVICES[deviceId].otp_algorithm,
+  //     otp_ctr: MOCKED_DEVICES[deviceId].otp_ctr
+  //   }
+  // }
+  const { fetcher } = useBackendInstanceRequest();
+
+  const { data, error, isValidating } = useSWR<
+    HttpResponseOk<MerchantBackend.OTP.OtpDeviceDetails>,
+    RequestError<MerchantBackend.ErrorDetail>
+  >([`/private/otp-devices/${deviceId}`], fetcher, {
+    refreshInterval: 0,
+    refreshWhenHidden: false,
+    revalidateOnFocus: false,
+    revalidateOnReconnect: false,
+    refreshWhenOffline: false,
+  });
+
+  if (isValidating) return { loading: true, data: data?.data };
+  if (data) {
+    return data;
+  }
+  if (error) return error.cause;
+  return { loading: true };
+}
diff --git a/packages/auditor-backoffice-ui/src/hooks/product.test.ts 
b/packages/auditor-backoffice-ui/src/hooks/product.test.ts
new file mode 100644
index 000000000..7cac10e25
--- /dev/null
+++ b/packages/auditor-backoffice-ui/src/hooks/product.test.ts
@@ -0,0 +1,362 @@
+/*
+ This file is part of GNU Taler
+ (C) 2021-2023 Taler Systems S.A.
+
+ GNU Taler is free software; you can redistribute it and/or modify it under the
+ terms of the GNU General Public License as published by the Free Software
+ Foundation; either version 3, or (at your option) any later version.
+
+ GNU Taler is distributed in the hope that it will be useful, but WITHOUT ANY
+ WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
+ A PARTICULAR PURPOSE.  See the GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License along with
+ GNU Taler; see the file COPYING.  If not, see <http://www.gnu.org/licenses/>
+ */
+
+/**
+ *
+ * @author Sebastian Javier Marchano (sebasjm)
+ */
+
+import * as tests from "@gnu-taler/web-util/testing";
+import { expect } from "chai";
+import { MerchantBackend } from "../declaration.js";
+import {
+  useInstanceProducts,
+  useProductAPI,
+  useProductDetails,
+} from "./product.js";
+import { ApiMockEnvironment } from "./testing.js";
+import {
+  API_CREATE_PRODUCT,
+  API_DELETE_PRODUCT,
+  API_GET_PRODUCT_BY_ID,
+  API_LIST_PRODUCTS,
+  API_UPDATE_PRODUCT_BY_ID,
+} from "./urls.js";
+
+describe("product api interaction with listing", () => {
+  it("should evict cache when creating a product", async () => {
+    const env = new ApiMockEnvironment();
+
+    env.addRequestExpectation(API_LIST_PRODUCTS, {
+      response: {
+        products: [{ product_id: "1234" }],
+      },
+    });
+    env.addRequestExpectation(API_GET_PRODUCT_BY_ID("1234"), {
+      response: { price: "ARS:12" } as MerchantBackend.Products.ProductDetail,
+    });
+
+    const hookBehavior = await tests.hookBehaveLikeThis(
+      () => {
+        const query = useInstanceProducts();
+        const api = useProductAPI();
+        return { query, api };
+      },
+      {},
+      [
+        ({ query, api }) => {
+          expect(query.loading).true;
+        },
+        ({ query, api }) => {
+          expect(env.assertJustExpectedRequestWereMade()).deep.eq({
+            result: "ok",
+          });
+          expect(query.loading).true;
+        },
+        ({ query, api }) => {
+          expect(query.loading).undefined;
+          expect(query.ok).true;
+          if (!query.ok) return;
+          expect(query.data).deep.equals([{ id: "1234", price: "ARS:12" }]);
+
+          env.addRequestExpectation(API_CREATE_PRODUCT, {
+            request: {
+              price: "ARS:23",
+            } as MerchantBackend.Products.ProductAddDetail,
+          });
+
+          env.addRequestExpectation(API_LIST_PRODUCTS, {
+            response: {
+              products: [{ product_id: "1234" }, { product_id: "2345" }],
+            },
+          });
+          env.addRequestExpectation(API_GET_PRODUCT_BY_ID("1234"), {
+            response: {
+              price: "ARS:12",
+            } as MerchantBackend.Products.ProductDetail,
+          });
+          env.addRequestExpectation(API_GET_PRODUCT_BY_ID("1234"), {
+            response: {
+              price: "ARS:12",
+            } as MerchantBackend.Products.ProductDetail,
+          });
+          env.addRequestExpectation(API_GET_PRODUCT_BY_ID("2345"), {
+            response: {
+              price: "ARS:23",
+            } as MerchantBackend.Products.ProductDetail,
+          });
+
+          api.createProduct({
+            price: "ARS:23",
+          } as any);
+        },
+        ({ query, api }) => {
+          expect(env.assertJustExpectedRequestWereMade()).deep.eq({
+            result: "ok",
+          });
+          expect(query.loading).true;
+        },
+        ({ query, api }) => {
+          expect(env.assertJustExpectedRequestWereMade()).deep.eq({
+            result: "ok",
+          });
+          expect(query.loading).undefined;
+          expect(query.ok).true;
+          if (!query.ok) return;
+          expect(query.data).deep.equals([
+            {
+              id: "1234",
+              price: "ARS:12",
+            },
+            {
+              id: "2345",
+              price: "ARS:23",
+            },
+          ]);
+        },
+      ],
+      env.buildTestingContext(),
+    );
+
+    expect(hookBehavior).deep.eq({ result: "ok" });
+    expect(env.assertJustExpectedRequestWereMade()).deep.eq({ result: "ok" });
+  });
+
+  it("should evict cache when updating a product", async () => {
+    const env = new ApiMockEnvironment();
+
+    env.addRequestExpectation(API_LIST_PRODUCTS, {
+      response: {
+        products: [{ product_id: "1234" }],
+      },
+    });
+    env.addRequestExpectation(API_GET_PRODUCT_BY_ID("1234"), {
+      response: { price: "ARS:12" } as MerchantBackend.Products.ProductDetail,
+    });
+
+    const hookBehavior = await tests.hookBehaveLikeThis(
+      () => {
+        const query = useInstanceProducts();
+        const api = useProductAPI();
+        return { query, api };
+      },
+      {},
+      [
+        ({ query, api }) => {
+          expect(query.loading).true;
+        },
+        ({ query, api }) => {
+          expect(query.loading).true;
+        },
+        ({ query, api }) => {
+          expect(env.assertJustExpectedRequestWereMade()).deep.eq({
+            result: "ok",
+          });
+          expect(query.loading).undefined;
+          expect(query.ok).true;
+          if (!query.ok) return;
+          expect(query.data).deep.equals([{ id: "1234", price: "ARS:12" }]);
+
+          env.addRequestExpectation(API_UPDATE_PRODUCT_BY_ID("1234"), {
+            request: {
+              price: "ARS:13",
+            } as MerchantBackend.Products.ProductPatchDetail,
+          });
+
+          env.addRequestExpectation(API_LIST_PRODUCTS, {
+            response: {
+              products: [{ product_id: "1234" }],
+            },
+          });
+          env.addRequestExpectation(API_GET_PRODUCT_BY_ID("1234"), {
+            response: {
+              price: "ARS:13",
+            } as MerchantBackend.Products.ProductDetail,
+          });
+
+          api.updateProduct("1234", {
+            price: "ARS:13",
+          } as any);
+        },
+        ({ query, api }) => {
+          expect(env.assertJustExpectedRequestWereMade()).deep.eq({
+            result: "ok",
+          });
+          expect(query.loading).undefined;
+          expect(query.ok).true;
+          if (!query.ok) return;
+          expect(query.data).deep.equals([
+            {
+              id: "1234",
+              price: "ARS:13",
+            },
+          ]);
+        },
+      ],
+      env.buildTestingContext(),
+    );
+
+    expect(hookBehavior).deep.eq({ result: "ok" });
+    expect(env.assertJustExpectedRequestWereMade()).deep.eq({ result: "ok" });
+  });
+
+  it("should evict cache when deleting a product", async () => {
+    const env = new ApiMockEnvironment();
+
+    env.addRequestExpectation(API_LIST_PRODUCTS, {
+      response: {
+        products: [{ product_id: "1234" }, { product_id: "2345" }],
+      },
+    });
+    env.addRequestExpectation(API_GET_PRODUCT_BY_ID("1234"), {
+      response: { price: "ARS:12" } as MerchantBackend.Products.ProductDetail,
+    });
+    env.addRequestExpectation(API_GET_PRODUCT_BY_ID("2345"), {
+      response: { price: "ARS:23" } as MerchantBackend.Products.ProductDetail,
+    });
+
+    const hookBehavior = await tests.hookBehaveLikeThis(
+      () => {
+        const query = useInstanceProducts();
+        const api = useProductAPI();
+        return { query, api };
+      },
+      {},
+      [
+        ({ query, api }) => {
+          expect(query.loading).true;
+        },
+        ({ query, api }) => {
+          expect(env.assertJustExpectedRequestWereMade()).deep.eq({
+            result: "ok",
+          });
+          expect(query.loading).true;
+        },
+        ({ query, api }) => {
+          expect(query.loading).undefined;
+          expect(query.ok).true;
+          if (!query.ok) return;
+          expect(query.data).deep.equals([
+            { id: "1234", price: "ARS:12" },
+            { id: "2345", price: "ARS:23" },
+          ]);
+
+          env.addRequestExpectation(API_DELETE_PRODUCT("2345"), {});
+
+          env.addRequestExpectation(API_LIST_PRODUCTS, {
+            response: {
+              products: [{ product_id: "1234" }],
+            },
+          });
+
+          env.addRequestExpectation(API_GET_PRODUCT_BY_ID("1234"), {
+            response: {
+              price: "ARS:12",
+            } as MerchantBackend.Products.ProductDetail,
+          });
+          api.deleteProduct("2345");
+        },
+        ({ query, api }) => {
+          expect(env.assertJustExpectedRequestWereMade()).deep.eq({
+            result: "ok",
+          });
+          expect(query.loading).true;
+        },
+        ({ query, api }) => {
+          expect(env.assertJustExpectedRequestWereMade()).deep.eq({
+            result: "ok",
+          });
+          expect(query.loading).undefined;
+          expect(query.ok).true;
+          if (!query.ok) return;
+          expect(query.data).deep.equals([{ id: "1234", price: "ARS:12" }]);
+        },
+      ],
+      env.buildTestingContext(),
+    );
+
+    expect(hookBehavior).deep.eq({ result: "ok" });
+    expect(env.assertJustExpectedRequestWereMade()).deep.eq({ result: "ok" });
+  });
+});
+
+describe("product api interaction with details", () => {
+  it("should evict cache when updating a product", async () => {
+    const env = new ApiMockEnvironment();
+
+    env.addRequestExpectation(API_GET_PRODUCT_BY_ID("12"), {
+      response: {
+        description: "this is a description",
+      } as MerchantBackend.Products.ProductDetail,
+    });
+
+    const hookBehavior = await tests.hookBehaveLikeThis(
+      () => {
+        const query = useProductDetails("12");
+        const api = useProductAPI();
+        return { query, api };
+      },
+      {},
+      [
+        ({ query, api }) => {
+          expect(query.loading).true;
+        },
+        ({ query, api }) => {
+          expect(env.assertJustExpectedRequestWereMade()).deep.eq({
+            result: "ok",
+          });
+          expect(query.loading).false;
+          expect(query.ok).true;
+          if (!query.ok) return;
+          expect(query.data).deep.equals({
+            description: "this is a description",
+          });
+
+          env.addRequestExpectation(API_UPDATE_PRODUCT_BY_ID("12"), {
+            request: {
+              description: "other description",
+            } as MerchantBackend.Products.ProductPatchDetail,
+          });
+
+          env.addRequestExpectation(API_GET_PRODUCT_BY_ID("12"), {
+            response: {
+              description: "other description",
+            } as MerchantBackend.Products.ProductDetail,
+          });
+
+          api.updateProduct("12", {
+            description: "other description",
+          } as any);
+        },
+        ({ query, api }) => {
+          expect(env.assertJustExpectedRequestWereMade()).deep.eq({
+            result: "ok",
+          });
+          expect(query.loading).false;
+          expect(query.ok).true;
+          if (!query.ok) return;
+          expect(query.data).deep.equals({
+            description: "other description",
+          });
+        },
+      ],
+      env.buildTestingContext(),
+    );
+
+    expect(hookBehavior).deep.eq({ result: "ok" });
+    expect(env.assertJustExpectedRequestWereMade()).deep.eq({ result: "ok" });
+  });
+});
diff --git a/packages/auditor-backoffice-ui/src/hooks/product.ts 
b/packages/auditor-backoffice-ui/src/hooks/product.ts
new file mode 100644
index 000000000..b8f55cb77
--- /dev/null
+++ b/packages/auditor-backoffice-ui/src/hooks/product.ts
@@ -0,0 +1,177 @@
+/*
+ This file is part of GNU Taler
+ (C) 2021-2023 Taler Systems S.A.
+
+ GNU Taler is free software; you can redistribute it and/or modify it under the
+ terms of the GNU General Public License as published by the Free Software
+ Foundation; either version 3, or (at your option) any later version.
+
+ GNU Taler is distributed in the hope that it will be useful, but WITHOUT ANY
+ WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
+ A PARTICULAR PURPOSE.  See the GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License along with
+ GNU Taler; see the file COPYING.  If not, see <http://www.gnu.org/licenses/>
+ */
+import {
+  HttpResponse,
+  HttpResponseOk,
+  RequestError,
+} from "@gnu-taler/web-util/browser";
+import { AuditorBackend, MerchantBackend, WithId } from "../declaration.js";
+import { useBackendInstanceRequest, useMatchMutate } from "./backend.js";
+
+// FIX default import https://github.com/microsoft/TypeScript/issues/49189
+import _useSWR, { SWRHook, useSWRConfig } from "swr";
+const useSWR = _useSWR as unknown as SWRHook;
+
+export interface ProductAPI {
+  getProduct: (
+    id: string,  
+  ) => Promise<void>;
+  createProduct: (
+    data: MerchantBackend.Products.ProductAddDetail,
+  ) => Promise<void>;
+  updateProduct: (
+    id: string,
+    data: MerchantBackend.Products.ProductPatchDetail,
+  ) => Promise<void>;
+  deleteProduct: (id: string) => Promise<void>;
+  lockProduct: (
+    id: string,
+    data: MerchantBackend.Products.LockRequest,
+  ) => Promise<void>;
+}
+
+export function useProductAPI(): ProductAPI {
+  const mutateAll = useMatchMutate();
+  const { mutate } = useSWRConfig();
+
+  const { request } = useBackendInstanceRequest();
+
+  const createProduct = async (
+    data: MerchantBackend.Products.ProductAddDetail,
+  ): Promise<void> => {
+    const res = await request(`/private/products`, {
+      method: "POST",
+      data,
+    });
+
+    return await mutateAll(/.*\/private\/products.*/);
+  };
+
+  const updateProduct = async (
+    productId: string,
+    data: MerchantBackend.Products.ProductPatchDetail,
+  ): Promise<void> => {
+    const r = await request(`/private/products/${productId}`, {
+      method: "PATCH",
+      data,
+    });
+
+    return await mutateAll(/.*\/private\/products.*/);
+  };
+
+  const deleteProduct = async (productId: string): Promise<void> => {
+    await request(`/private/products/${productId}`, {
+      method: "DELETE",
+    });
+    await mutate([`/private/products`]);
+  };
+
+  const lockProduct = async (
+    productId: string,
+    data: MerchantBackend.Products.LockRequest,
+  ): Promise<void> => {
+    await request(`/private/products/${productId}/lock`, {
+      method: "POST",
+      data,
+    });
+
+    return await mutateAll(/.*"\/private\/products.*/);
+  };
+
+  const getProduct = async (
+    productId: string,
+  ): Promise<void> => {
+    await request(`/private/products/${productId}`, {
+      method: "GET",
+    });
+
+    return
+  };
+
+  return { createProduct, updateProduct, deleteProduct, lockProduct, 
getProduct };
+}
+
+export function useInstanceProducts(): HttpResponse<
+  (MerchantBackend.Products.ProductDetail & WithId)[],
+  MerchantBackend.ErrorDetail
+> {
+  const { fetcher, multiFetcher } = useBackendInstanceRequest();
+
+  const { data: list, error: listError } = useSWR<
+    HttpResponseOk<MerchantBackend.Products.InventorySummaryResponse>,
+    RequestError<MerchantBackend.ErrorDetail>
+  >([`/private/products`], fetcher, {
+    refreshInterval: 0,
+    refreshWhenHidden: false,
+    revalidateOnFocus: false,
+    revalidateOnReconnect: false,
+    refreshWhenOffline: false,
+  });
+
+  const paths = (list?.data.products || []).map(
+    (p) => `/deposit-confirmation/${p.serial_id}`,
+  );
+  const { data: products, error: productError } = useSWR<
+    
HttpResponseOk<AuditorBackend.DepositConfirmation.DepositConfirmationDetail>[],
+    RequestError<AuditorBackend.ErrorDetail>
+  >([paths], multiFetcher, {
+    refreshInterval: 0,
+    refreshWhenHidden: false,
+    revalidateOnFocus: false,
+    revalidateOnReconnect: false,
+    refreshWhenOffline: false,
+  });
+
+  if (listError) return listError.cause;
+  if (productError) return productError.cause;
+
+  if (products) {
+    const dataWithId = products.map((d) => {
+      //take the id from the queried url
+      return {
+        ...d.data,
+        id: d.info?.url.replace(/.*\/private\/products\//, "") || "",
+      };
+    });
+    return { ok: true, data: dataWithId };
+  }
+  return { loading: true };
+}
+
+export function useProductDetails(
+  productId: string,
+): HttpResponse<
+  MerchantBackend.Products.ProductDetail,
+  MerchantBackend.ErrorDetail
+> {
+  const { fetcher } = useBackendInstanceRequest();
+
+  const { data, error, isValidating } = useSWR<
+    HttpResponseOk<MerchantBackend.Products.ProductDetail>,
+    RequestError<MerchantBackend.ErrorDetail>
+  >([`/private/products/${productId}`], fetcher, {
+    refreshInterval: 0,
+    refreshWhenHidden: false,
+    revalidateOnFocus: false,
+    revalidateOnReconnect: false,
+    refreshWhenOffline: false,
+  });
+
+  if (isValidating) return { loading: true, data: data?.data };
+  if (data) return data;
+  if (error) return error.cause;
+  return { loading: true };
+}
diff --git a/packages/auditor-backoffice-ui/src/hooks/reserve.test.ts 
b/packages/auditor-backoffice-ui/src/hooks/reserve.test.ts
new file mode 100644
index 000000000..b3eecd754
--- /dev/null
+++ b/packages/auditor-backoffice-ui/src/hooks/reserve.test.ts
@@ -0,0 +1,448 @@
+/*
+ This file is part of GNU Taler
+ (C) 2021-2023 Taler Systems S.A.
+
+ GNU Taler is free software; you can redistribute it and/or modify it under the
+ terms of the GNU General Public License as published by the Free Software
+ Foundation; either version 3, or (at your option) any later version.
+
+ GNU Taler is distributed in the hope that it will be useful, but WITHOUT ANY
+ WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
+ A PARTICULAR PURPOSE.  See the GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License along with
+ GNU Taler; see the file COPYING.  If not, see <http://www.gnu.org/licenses/>
+ */
+
+/**
+ *
+ * @author Sebastian Javier Marchano (sebasjm)
+ */
+
+import { expect } from "chai";
+import { MerchantBackend } from "../declaration.js";
+import {
+  useInstanceReserves,
+  useReserveDetails,
+  useReservesAPI,
+  useRewardDetails,
+} from "./reserves.js";
+import { ApiMockEnvironment } from "./testing.js";
+import {
+  API_AUTHORIZE_REWARD,
+  API_AUTHORIZE_REWARD_FOR_RESERVE,
+  API_CREATE_RESERVE,
+  API_DELETE_RESERVE,
+  API_GET_RESERVE_BY_ID,
+  API_GET_REWARD_BY_ID,
+  API_LIST_RESERVES,
+} from "./urls.js";
+import * as tests from "@gnu-taler/web-util/testing";
+
+describe("reserve api interaction with listing", () => {
+  it("should evict cache when creating a reserve", async () => {
+    const env = new ApiMockEnvironment();
+
+    env.addRequestExpectation(API_LIST_RESERVES, {
+      response: {
+        reserves: [
+          {
+            reserve_pub: "11",
+          } as MerchantBackend.Rewards.ReserveStatusEntry,
+        ],
+      },
+    });
+
+    const hookBehavior = await tests.hookBehaveLikeThis(
+      () => {
+        const api = useReservesAPI();
+        const query = useInstanceReserves();
+        return { query, api };
+      },
+      {},
+      [
+        ({ query, api }) => {
+          expect(query.loading).true;
+        },
+        ({ query, api }) => {
+          expect(query.loading).false;
+          expect(query.ok).true;
+          if (!query.ok) return;
+          expect(query.data).deep.equals({
+            reserves: [{ reserve_pub: "11" }],
+          });
+
+          env.addRequestExpectation(API_CREATE_RESERVE, {
+            request: {
+              initial_balance: "ARS:3333",
+              exchange_url: "http://url";,
+              wire_method: "iban",
+            },
+            response: {
+              reserve_pub: "22",
+              accounts: [],
+            },
+          });
+
+          env.addRequestExpectation(API_LIST_RESERVES, {
+            response: {
+              reserves: [
+                {
+                  reserve_pub: "11",
+                } as MerchantBackend.Rewards.ReserveStatusEntry,
+                {
+                  reserve_pub: "22",
+                } as MerchantBackend.Rewards.ReserveStatusEntry,
+              ],
+            },
+          });
+
+          api.createReserve({
+            initial_balance: "ARS:3333",
+            exchange_url: "http://url";,
+            wire_method: "iban",
+          });
+        },
+        ({ query, api }) => {
+          expect(env.assertJustExpectedRequestWereMade()).deep.eq({
+            result: "ok",
+          });
+          expect(query.loading).false;
+          expect(query.ok).true;
+          if (!query.ok) return;
+
+          expect(query.data).deep.equals({
+            reserves: [
+              {
+                reserve_pub: "11",
+              } as MerchantBackend.Rewards.ReserveStatusEntry,
+              {
+                reserve_pub: "22",
+              } as MerchantBackend.Rewards.ReserveStatusEntry,
+            ],
+          });
+        },
+      ],
+      env.buildTestingContext(),
+    );
+
+    expect(hookBehavior).deep.eq({ result: "ok" });
+    expect(env.assertJustExpectedRequestWereMade()).deep.eq({ result: "ok" });
+  });
+
+  it("should evict cache when deleting a reserve", async () => {
+    const env = new ApiMockEnvironment();
+
+    env.addRequestExpectation(API_LIST_RESERVES, {
+      response: {
+        reserves: [
+          {
+            reserve_pub: "11",
+          } as MerchantBackend.Rewards.ReserveStatusEntry,
+          {
+            reserve_pub: "22",
+          } as MerchantBackend.Rewards.ReserveStatusEntry,
+          {
+            reserve_pub: "33",
+          } as MerchantBackend.Rewards.ReserveStatusEntry,
+        ],
+      },
+    });
+
+    const hookBehavior = await tests.hookBehaveLikeThis(
+      () => {
+        const api = useReservesAPI();
+        const query = useInstanceReserves();
+        return { query, api };
+      },
+      {},
+      [
+        ({ query, api }) => {
+          expect(query.loading).true;
+        },
+        ({ query, api }) => {
+          expect(env.assertJustExpectedRequestWereMade()).deep.eq({
+            result: "ok",
+          });
+
+          expect(query.loading).false;
+          expect(query.ok).true;
+          if (!query.ok) return;
+          expect(query.data).deep.equals({
+            reserves: [
+              { reserve_pub: "11" },
+              { reserve_pub: "22" },
+              { reserve_pub: "33" },
+            ],
+          });
+
+          env.addRequestExpectation(API_DELETE_RESERVE("11"), {});
+          env.addRequestExpectation(API_LIST_RESERVES, {
+            response: {
+              reserves: [
+                {
+                  reserve_pub: "22",
+                } as MerchantBackend.Rewards.ReserveStatusEntry,
+                {
+                  reserve_pub: "33",
+                } as MerchantBackend.Rewards.ReserveStatusEntry,
+              ],
+            },
+          });
+
+          api.deleteReserve("11");
+        },
+        ({ query, api }) => {
+          expect(env.assertJustExpectedRequestWereMade()).deep.eq({
+            result: "ok",
+          });
+          expect(query.loading).false;
+          expect(query.ok).true;
+          if (!query.ok) return;
+          expect(query.data).deep.equals({
+            reserves: [{ reserve_pub: "22" }, { reserve_pub: "33" }],
+          });
+        },
+      ],
+      env.buildTestingContext(),
+    );
+
+    expect(hookBehavior).deep.eq({ result: "ok" });
+    expect(env.assertJustExpectedRequestWereMade()).deep.eq({ result: "ok" });
+  });
+});
+
+describe("reserve api interaction with details", () => {
+  it("should evict cache when adding a reward for a specific reserve", async 
() => {
+    const env = new ApiMockEnvironment();
+
+    env.addRequestExpectation(API_GET_RESERVE_BY_ID("11"), {
+      response: {
+        accounts: [{ payto_uri: "payto://here" }],
+        rewards: [{ reason: "why?", reward_id: "id1", total_amount: "USD:10" 
}],
+      } as MerchantBackend.Rewards.ReserveDetail,
+      qparam: {
+        rewards: "yes",
+      },
+    });
+
+    const hookBehavior = await tests.hookBehaveLikeThis(
+      () => {
+        const api = useReservesAPI();
+        const query = useReserveDetails("11");
+        return { query, api };
+      },
+      {},
+      [
+        ({ query, api }) => {
+          expect(query.loading).true;
+        },
+        ({ query, api }) => {
+          expect(env.assertJustExpectedRequestWereMade()).deep.eq({
+            result: "ok",
+          });
+          expect(query.loading).false;
+          expect(query.ok).true;
+          if (!query.ok) return;
+          expect(query.data).deep.equals({
+            accounts: [{ payto_uri: "payto://here" }],
+            rewards: [{ reason: "why?", reward_id: "id1", total_amount: 
"USD:10" }],
+          });
+
+          env.addRequestExpectation(API_AUTHORIZE_REWARD_FOR_RESERVE("11"), {
+            request: {
+              amount: "USD:12",
+              justification: "not",
+              next_url: "http://taler.net";,
+            },
+            response: {
+              reward_id: "id2",
+              taler_reward_uri: "uri",
+              reward_expiration: { t_s: 1 },
+              reward_status_url: "url",
+            },
+          });
+
+          env.addRequestExpectation(API_GET_RESERVE_BY_ID("11"), {
+            response: {
+              accounts: [{ payto_uri: "payto://here" }],
+              rewards: [
+                { reason: "why?", reward_id: "id1", total_amount: "USD:10" },
+                { reason: "not", reward_id: "id2", total_amount: "USD:12" },
+              ],
+            } as MerchantBackend.Rewards.ReserveDetail,
+            qparam: {
+              rewards: "yes",
+            },
+          });
+
+          api.authorizeRewardReserve("11", {
+            amount: "USD:12",
+            justification: "not",
+            next_url: "http://taler.net";,
+          });
+        },
+        ({ query, api }) => {
+          expect(env.assertJustExpectedRequestWereMade()).deep.eq({
+            result: "ok",
+          });
+          expect(query.loading).false;
+
+          expect(query.loading).false;
+          expect(query.ok).true;
+          if (!query.ok) return;
+
+          expect(query.data).deep.equals({
+            accounts: [{ payto_uri: "payto://here" }],
+            rewards: [
+              { reason: "why?", reward_id: "id1", total_amount: "USD:10" },
+              { reason: "not", reward_id: "id2", total_amount: "USD:12" },
+            ],
+          });
+        },
+      ],
+      env.buildTestingContext(),
+    );
+
+    expect(hookBehavior).deep.eq({ result: "ok" });
+    expect(env.assertJustExpectedRequestWereMade()).deep.eq({ result: "ok" });
+  });
+
+  it("should evict cache when adding a reward for a random reserve", async () 
=> {
+    const env = new ApiMockEnvironment();
+
+    env.addRequestExpectation(API_GET_RESERVE_BY_ID("11"), {
+      response: {
+        accounts: [{ payto_uri: "payto://here" }],
+        rewards: [{ reason: "why?", reward_id: "id1", total_amount: "USD:10" 
}],
+      } as MerchantBackend.Rewards.ReserveDetail,
+      qparam: {
+        rewards: "yes",
+      },
+    });
+
+    const hookBehavior = await tests.hookBehaveLikeThis(
+      () => {
+        const api = useReservesAPI();
+        const query = useReserveDetails("11");
+        return { query, api };
+      },
+      {},
+      [
+        ({ query, api }) => {
+          expect(query.loading).true;
+        },
+        ({ query, api }) => {
+          expect(env.assertJustExpectedRequestWereMade()).deep.eq({
+            result: "ok",
+          });
+          expect(query.loading).false;
+          expect(query.ok).true;
+          if (!query.ok) return;
+          expect(query.data).deep.equals({
+            accounts: [{ payto_uri: "payto://here" }],
+            rewards: [{ reason: "why?", reward_id: "id1", total_amount: 
"USD:10" }],
+          });
+
+          env.addRequestExpectation(API_AUTHORIZE_REWARD, {
+            request: {
+              amount: "USD:12",
+              justification: "not",
+              next_url: "http://taler.net";,
+            },
+            response: {
+              reward_id: "id2",
+              taler_reward_uri: "uri",
+              reward_expiration: { t_s: 1 },
+              reward_status_url: "url",
+            },
+          });
+
+          env.addRequestExpectation(API_GET_RESERVE_BY_ID("11"), {
+            response: {
+              accounts: [{ payto_uri: "payto://here" }],
+              rewards: [
+                { reason: "why?", reward_id: "id1", total_amount: "USD:10" },
+                { reason: "not", reward_id: "id2", total_amount: "USD:12" },
+              ],
+            } as MerchantBackend.Rewards.ReserveDetail,
+            qparam: {
+              rewards: "yes",
+            },
+          });
+
+          api.authorizeReward({
+            amount: "USD:12",
+            justification: "not",
+            next_url: "http://taler.net";,
+          });
+        },
+        ({ query, api }) => {
+          expect(env.assertJustExpectedRequestWereMade()).deep.eq({
+            result: "ok",
+          });
+          expect(query.loading).false;
+          expect(query.ok).true;
+          if (!query.ok) return;
+
+          expect(query.data).deep.equals({
+            accounts: [{ payto_uri: "payto://here" }],
+            rewards: [
+              { reason: "why?", reward_id: "id1", total_amount: "USD:10" },
+              { reason: "not", reward_id: "id2", total_amount: "USD:12" },
+            ],
+          });
+        },
+      ],
+      env.buildTestingContext(),
+    );
+
+    expect(hookBehavior).deep.eq({ result: "ok" });
+    expect(env.assertJustExpectedRequestWereMade()).deep.eq({ result: "ok" });
+  });
+});
+
+describe("reserve api interaction with reward details", () => {
+  it("should list rewards", async () => {
+    const env = new ApiMockEnvironment();
+
+    env.addRequestExpectation(API_GET_REWARD_BY_ID("11"), {
+      response: {
+        total_picked_up: "USD:12",
+        reason: "not",
+      } as MerchantBackend.Rewards.RewardDetails,
+      qparam: {
+        pickups: "yes",
+      },
+    });
+
+    const hookBehavior = await tests.hookBehaveLikeThis(
+      () => {
+        const query = useRewardDetails("11");
+        return { query };
+      },
+      {},
+      [
+        ({ query }) => {
+          expect(env.assertJustExpectedRequestWereMade()).deep.eq({
+            result: "ok",
+          });
+          expect(query.loading).true;
+        },
+        ({ query }) => {
+          expect(query.loading).false;
+          expect(query.ok).true;
+          if (!query.ok) return;
+          expect(query.data).deep.equals({
+            total_picked_up: "USD:12",
+            reason: "not",
+          });
+        },
+      ],
+      env.buildTestingContext(),
+    );
+
+    expect(hookBehavior).deep.eq({ result: "ok" });
+    expect(env.assertJustExpectedRequestWereMade()).deep.eq({ result: "ok" });
+  });
+});
diff --git a/packages/auditor-backoffice-ui/src/hooks/reserves.ts 
b/packages/auditor-backoffice-ui/src/hooks/reserves.ts
new file mode 100644
index 000000000..b719bfbe6
--- /dev/null
+++ b/packages/auditor-backoffice-ui/src/hooks/reserves.ts
@@ -0,0 +1,181 @@
+/*
+ This file is part of GNU Taler
+ (C) 2021-2023 Taler Systems S.A.
+
+ GNU Taler is free software; you can redistribute it and/or modify it under the
+ terms of the GNU General Public License as published by the Free Software
+ Foundation; either version 3, or (at your option) any later version.
+
+ GNU Taler is distributed in the hope that it will be useful, but WITHOUT ANY
+ WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
+ A PARTICULAR PURPOSE.  See the GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License along with
+ GNU Taler; see the file COPYING.  If not, see <http://www.gnu.org/licenses/>
+ */
+import {
+  HttpResponse,
+  HttpResponseOk,
+  RequestError,
+} from "@gnu-taler/web-util/browser";
+import { MerchantBackend } from "../declaration.js";
+import { useBackendInstanceRequest, useMatchMutate } from "./backend.js";
+
+// FIX default import https://github.com/microsoft/TypeScript/issues/49189
+import _useSWR, { SWRHook, useSWRConfig } from "swr";
+const useSWR = _useSWR as unknown as SWRHook;
+
+export function useReservesAPI(): ReserveMutateAPI {
+  const mutateAll = useMatchMutate();
+  const { mutate } = useSWRConfig();
+  const { request } = useBackendInstanceRequest();
+
+  const createReserve = async (
+    data: MerchantBackend.Rewards.ReserveCreateRequest,
+  ): Promise<
+    HttpResponseOk<MerchantBackend.Rewards.ReserveCreateConfirmation>
+  > => {
+    const res = await 
request<MerchantBackend.Rewards.ReserveCreateConfirmation>(
+      `/private/reserves`,
+      {
+        method: "POST",
+        data,
+      },
+    );
+
+    //evict reserve list query
+    await mutateAll(/.*private\/reserves.*/);
+
+    return res;
+  };
+
+  const authorizeRewardReserve = async (
+    pub: string,
+    data: MerchantBackend.Rewards.RewardCreateRequest,
+  ): Promise<HttpResponseOk<MerchantBackend.Rewards.RewardCreateConfirmation>> 
=> {
+    const res = await 
request<MerchantBackend.Rewards.RewardCreateConfirmation>(
+      `/private/reserves/${pub}/authorize-reward`,
+      {
+        method: "POST",
+        data,
+      },
+    );
+
+    //evict reserve details query
+    await mutate([`/private/reserves/${pub}`]);
+
+    return res;
+  };
+
+  const authorizeReward = async (
+    data: MerchantBackend.Rewards.RewardCreateRequest,
+  ): Promise<HttpResponseOk<MerchantBackend.Rewards.RewardCreateConfirmation>> 
=> {
+    const res = await 
request<MerchantBackend.Rewards.RewardCreateConfirmation>(
+      `/private/rewards`,
+      {
+        method: "POST",
+        data,
+      },
+    );
+
+    //evict all details query
+    await mutateAll(/.*private\/reserves\/.*/);
+
+    return res;
+  };
+
+  const deleteReserve = async (
+    pub: string,
+  ): Promise<HttpResponse<void, MerchantBackend.ErrorDetail>> => {
+    const res = await request<void>(`/private/reserves/${pub}`, {
+      method: "DELETE",
+    });
+
+    //evict reserve list query
+    await mutateAll(/.*private\/reserves.*/);
+
+    return res;
+  };
+
+  return { createReserve, authorizeReward, authorizeRewardReserve, 
deleteReserve };
+}
+
+export interface ReserveMutateAPI {
+  createReserve: (
+    data: MerchantBackend.Rewards.ReserveCreateRequest,
+  ) => 
Promise<HttpResponseOk<MerchantBackend.Rewards.ReserveCreateConfirmation>>;
+  authorizeRewardReserve: (
+    id: string,
+    data: MerchantBackend.Rewards.RewardCreateRequest,
+  ) => 
Promise<HttpResponseOk<MerchantBackend.Rewards.RewardCreateConfirmation>>;
+  authorizeReward: (
+    data: MerchantBackend.Rewards.RewardCreateRequest,
+  ) => 
Promise<HttpResponseOk<MerchantBackend.Rewards.RewardCreateConfirmation>>;
+  deleteReserve: (
+    id: string,
+  ) => Promise<HttpResponse<void, MerchantBackend.ErrorDetail>>;
+}
+
+export function useInstanceReserves(): HttpResponse<
+  MerchantBackend.Rewards.RewardReserveStatus,
+  MerchantBackend.ErrorDetail
+> {
+  const { fetcher } = useBackendInstanceRequest();
+
+  const { data, error, isValidating } = useSWR<
+    HttpResponseOk<MerchantBackend.Rewards.RewardReserveStatus>,
+    RequestError<MerchantBackend.ErrorDetail>
+  >([`/private/reserves`], fetcher);
+
+  if (isValidating) return { loading: true, data: data?.data };
+  if (data) return data;
+  if (error) return error.cause;
+  return { loading: true };
+}
+
+export function useReserveDetails(
+  reserveId: string,
+): HttpResponse<
+  MerchantBackend.Rewards.ReserveDetail,
+  MerchantBackend.ErrorDetail
+> {
+  const { reserveDetailFetcher } = useBackendInstanceRequest();
+
+  const { data, error, isValidating } = useSWR<
+    HttpResponseOk<MerchantBackend.Rewards.ReserveDetail>,
+    RequestError<MerchantBackend.ErrorDetail>
+  >([`/private/reserves/${reserveId}`], reserveDetailFetcher, {
+    refreshInterval: 0,
+    refreshWhenHidden: false,
+    revalidateOnFocus: false,
+    revalidateOnReconnect: false,
+    refreshWhenOffline: false,
+  });
+
+  if (isValidating) return { loading: true, data: data?.data };
+  if (data) return data;
+  if (error) return error.cause;
+  return { loading: true };
+}
+
+export function useRewardDetails(
+  rewardId: string,
+): HttpResponse<MerchantBackend.Rewards.RewardDetails, 
MerchantBackend.ErrorDetail> {
+  const { rewardsDetailFetcher } = useBackendInstanceRequest();
+
+  const { data, error, isValidating } = useSWR<
+    HttpResponseOk<MerchantBackend.Rewards.RewardDetails>,
+    RequestError<MerchantBackend.ErrorDetail>
+  >([`/private/rewards/${rewardId}`], rewardsDetailFetcher, {
+    refreshInterval: 0,
+    refreshWhenHidden: false,
+    revalidateOnFocus: false,
+    revalidateOnReconnect: false,
+    refreshWhenOffline: false,
+  });
+
+  if (isValidating) return { loading: true, data: data?.data };
+  if (data) return data;
+  if (error) return error.cause;
+  return { loading: true };
+}
diff --git a/packages/auditor-backoffice-ui/src/hooks/templates.ts 
b/packages/auditor-backoffice-ui/src/hooks/templates.ts
new file mode 100644
index 000000000..ee8728cc8
--- /dev/null
+++ b/packages/auditor-backoffice-ui/src/hooks/templates.ts
@@ -0,0 +1,266 @@
+/*
+ This file is part of GNU Taler
+ (C) 2021-2023 Taler Systems S.A.
+
+ GNU Taler is free software; you can redistribute it and/or modify it under the
+ terms of the GNU General Public License as published by the Free Software
+ Foundation; either version 3, or (at your option) any later version.
+
+ GNU Taler is distributed in the hope that it will be useful, but WITHOUT ANY
+ WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
+ A PARTICULAR PURPOSE.  See the GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License along with
+ GNU Taler; see the file COPYING.  If not, see <http://www.gnu.org/licenses/>
+ */
+import {
+  HttpResponse,
+  HttpResponseOk,
+  HttpResponsePaginated,
+  RequestError,
+} from "@gnu-taler/web-util/browser";
+import { useEffect, useState } from "preact/hooks";
+import { MerchantBackend } from "../declaration.js";
+import { MAX_RESULT_SIZE, PAGE_SIZE } from "../utils/constants.js";
+import { useBackendInstanceRequest, useMatchMutate } from "./backend.js";
+
+// FIX default import https://github.com/microsoft/TypeScript/issues/49189
+import _useSWR, { SWRHook } from "swr";
+const useSWR = _useSWR as unknown as SWRHook;
+
+export function useTemplateAPI(): TemplateAPI {
+  const mutateAll = useMatchMutate();
+  const { request } = useBackendInstanceRequest();
+
+  const createTemplate = async (
+    data: MerchantBackend.Template.TemplateAddDetails,
+  ): Promise<HttpResponseOk<void>> => {
+    const res = await request<void>(`/private/templates`, {
+      method: "POST",
+      data,
+    });
+    await mutateAll(/.*private\/templates.*/);
+    return res;
+  };
+
+  const updateTemplate = async (
+    templateId: string,
+    data: MerchantBackend.Template.TemplatePatchDetails,
+  ): Promise<HttpResponseOk<void>> => {
+    const res = await request<void>(`/private/templates/${templateId}`, {
+      method: "PATCH",
+      data,
+    });
+    await mutateAll(/.*private\/templates.*/);
+    return res;
+  };
+
+  const deleteTemplate = async (
+    templateId: string,
+  ): Promise<HttpResponseOk<void>> => {
+    const res = await request<void>(`/private/templates/${templateId}`, {
+      method: "DELETE",
+    });
+    await mutateAll(/.*private\/templates.*/);
+    return res;
+  };
+
+  const createOrderFromTemplate = async (
+    templateId: string,
+    data: MerchantBackend.Template.UsingTemplateDetails,
+  ): Promise<
+    HttpResponseOk<MerchantBackend.Template.UsingTemplateResponse>
+  > => {
+    const res = await request<MerchantBackend.Template.UsingTemplateResponse>(
+      `/templates/${templateId}`,
+      {
+        method: "POST",
+        data,
+      },
+    );
+    await mutateAll(/.*private\/templates.*/);
+    return res;
+  };
+
+  const testTemplateExist = async (
+    templateId: string,
+  ): Promise<HttpResponseOk<void>> => {
+    const res = await request<void>(`/private/templates/${templateId}`, { 
method: "GET", });
+    return res;
+  };
+
+
+  return {
+    createTemplate,
+    updateTemplate,
+    deleteTemplate,
+    testTemplateExist,
+    createOrderFromTemplate,
+  };
+}
+
+export interface TemplateAPI {
+  createTemplate: (
+    data: MerchantBackend.Template.TemplateAddDetails,
+  ) => Promise<HttpResponseOk<void>>;
+  updateTemplate: (
+    id: string,
+    data: MerchantBackend.Template.TemplatePatchDetails,
+  ) => Promise<HttpResponseOk<void>>;
+  testTemplateExist: (
+    id: string
+  ) => Promise<HttpResponseOk<void>>;
+  deleteTemplate: (id: string) => Promise<HttpResponseOk<void>>;
+  createOrderFromTemplate: (
+    id: string,
+    data: MerchantBackend.Template.UsingTemplateDetails,
+  ) => Promise<HttpResponseOk<MerchantBackend.Template.UsingTemplateResponse>>;
+}
+
+export interface InstanceTemplateFilter {
+  //FIXME: add filter to the template list
+  position?: string;
+}
+
+export function useInstanceTemplates(
+  args?: InstanceTemplateFilter,
+  updatePosition?: (id: string) => void,
+): HttpResponsePaginated<
+  MerchantBackend.Template.TemplateSummaryResponse,
+  MerchantBackend.ErrorDetail
+> {
+  const { templateFetcher } = useBackendInstanceRequest();
+
+  const [pageBefore, setPageBefore] = useState(1);
+  const [pageAfter, setPageAfter] = useState(1);
+
+  const totalAfter = pageAfter * PAGE_SIZE;
+  const totalBefore = args?.position ? pageBefore * PAGE_SIZE : 0;
+
+  /**
+   * FIXME: this can be cleaned up a little
+   *
+   * the logic of double query should be inside the orderFetch so from the 
hook perspective and cache
+   * is just one query and one error status
+   */
+  const {
+    data: beforeData,
+    error: beforeError,
+    isValidating: loadingBefore,
+  } = useSWR<
+    HttpResponseOk<MerchantBackend.Template.TemplateSummaryResponse>,
+    RequestError<MerchantBackend.ErrorDetail>>(
+      [
+        `/private/templates`,
+        args?.position,
+        totalBefore,
+      ],
+      templateFetcher,
+    );
+  const {
+    data: afterData,
+    error: afterError,
+    isValidating: loadingAfter,
+  } = useSWR<
+    HttpResponseOk<MerchantBackend.Template.TemplateSummaryResponse>,
+    RequestError<MerchantBackend.ErrorDetail>
+  >([`/private/templates`, args?.position, -totalAfter], templateFetcher);
+
+  //this will save last result
+  const [lastBefore, setLastBefore] = useState<
+    HttpResponse<
+      MerchantBackend.Template.TemplateSummaryResponse,
+      MerchantBackend.ErrorDetail
+    >
+  >({ loading: true });
+
+  const [lastAfter, setLastAfter] = useState<
+    HttpResponse<
+      MerchantBackend.Template.TemplateSummaryResponse,
+      MerchantBackend.ErrorDetail
+    >
+  >({ loading: true });
+  useEffect(() => {
+    if (afterData) setLastAfter(afterData);
+    if (beforeData) setLastBefore(beforeData);
+  }, [afterData, beforeData]);
+
+  if (beforeError) return beforeError.cause;
+  if (afterError) return afterError.cause;
+
+  // if the query returns less that we ask, then we have reach the end or 
beginning
+  const isReachingEnd =
+    afterData && afterData.data.templates.length < totalAfter;
+  const isReachingStart = args?.position === undefined
+    ||
+    (beforeData && beforeData.data.templates.length < totalBefore);
+
+  const pagination = {
+    isReachingEnd,
+    isReachingStart,
+    loadMore: () => {
+      if (!afterData || isReachingEnd) return;
+      if (afterData.data.templates.length < MAX_RESULT_SIZE) {
+        setPageAfter(pageAfter + 1);
+      } else {
+        const from = 
`${afterData.data.templates[afterData.data.templates.length - 1]
+          .template_id
+          }`;
+        if (from && updatePosition) updatePosition(from);
+      }
+    },
+    loadMorePrev: () => {
+      if (!beforeData || isReachingStart) return;
+      if (beforeData.data.templates.length < MAX_RESULT_SIZE) {
+        setPageBefore(pageBefore + 1);
+      } else if (beforeData) {
+        const from = 
`${beforeData.data.templates[beforeData.data.templates.length - 1]
+          .template_id
+          }`;
+        if (from && updatePosition) updatePosition(from);
+      }
+    },
+  };
+
+  // const templates = !afterData ? [] : (afterData || 
lastAfter).data.templates;
+  const templates =
+    !beforeData || !afterData
+      ? []
+      : (beforeData || lastBefore).data.templates
+        .slice()
+        .reverse()
+        .concat((afterData || lastAfter).data.templates);
+  if (loadingAfter || loadingBefore)
+    return { loading: true, data: { templates } };
+  if (beforeData && afterData) {
+    return { ok: true, data: { templates }, ...pagination };
+  }
+  return { loading: true };
+}
+
+export function useTemplateDetails(
+  templateId: string,
+): HttpResponse<
+  MerchantBackend.Template.TemplateDetails,
+  MerchantBackend.ErrorDetail
+> {
+  const { templateFetcher } = useBackendInstanceRequest();
+
+  const { data, error, isValidating } = useSWR<
+    HttpResponseOk<MerchantBackend.Template.TemplateDetails>,
+    RequestError<MerchantBackend.ErrorDetail>
+  >([`/private/templates/${templateId}`], templateFetcher, {
+    refreshInterval: 0,
+    refreshWhenHidden: false,
+    revalidateOnFocus: false,
+    revalidateOnReconnect: false,
+    refreshWhenOffline: false,
+  });
+
+  if (isValidating) return { loading: true, data: data?.data };
+  if (data) {
+    return data;
+  }
+  if (error) return error.cause;
+  return { loading: true };
+}
diff --git a/packages/auditor-backoffice-ui/src/hooks/testing.tsx 
b/packages/auditor-backoffice-ui/src/hooks/testing.tsx
new file mode 100644
index 000000000..3ea22475b
--- /dev/null
+++ b/packages/auditor-backoffice-ui/src/hooks/testing.tsx
@@ -0,0 +1,180 @@
+/*
+ This file is part of GNU Taler
+ (C) 2021-2023 Taler Systems S.A.
+
+ GNU Taler is free software; you can redistribute it and/or modify it under the
+ terms of the GNU General Public License as published by the Free Software
+ Foundation; either version 3, or (at your option) any later version.
+
+ GNU Taler is distributed in the hope that it will be useful, but WITHOUT ANY
+ WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
+ A PARTICULAR PURPOSE.  See the GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License along with
+ GNU Taler; see the file COPYING.  If not, see <http://www.gnu.org/licenses/>
+ */
+
+/**
+ *
+ * @author Sebastian Javier Marchano (sebasjm)
+ */
+
+import { MockEnvironment } from "@gnu-taler/web-util/testing";
+import { ComponentChildren, FunctionalComponent, h, VNode } from "preact";
+import { HttpRequestLibrary, HttpRequestOptions, HttpResponse } from 
"@gnu-taler/taler-util/http";
+import { SWRConfig } from "swr";
+import { ApiContextProvider } from "@gnu-taler/web-util/browser";
+import { BackendContextProvider } from "../context/backend.js";
+import { InstanceContextProvider } from "../context/instance.js";
+import { HttpResponseOk, RequestOptions } from "@gnu-taler/web-util/browser";
+import { TalerBankIntegrationHttpClient, TalerCoreBankHttpClient } from 
"@gnu-taler/taler-util";
+
+export class ApiMockEnvironment extends MockEnvironment {
+  constructor(debug = false) {
+    super(debug);
+  }
+
+  mockApiIfNeeded(): void {
+    null; // do nothing
+  }
+
+  public buildTestingContext(): FunctionalComponent<{
+    children: ComponentChildren;
+  }> {
+    const __SAVE_REQUEST_AND_GET_MOCKED_RESPONSE =
+      this.saveRequestAndGetMockedResponse.bind(this);
+
+    return function TestingContext({
+      children,
+    }: {
+      children: ComponentChildren;
+    }): VNode {
+
+      async function request<T>(
+        base: string,
+        path: string,
+        options: RequestOptions = {},
+      ): Promise<HttpResponseOk<T>> {
+        const _url = new URL(`${base}${path}`);
+        // Object.entries(options.params ?? {}).forEach(([key, value]) => {
+        //   _url.searchParams.set(key, String(value));
+        // });
+
+        const mocked = __SAVE_REQUEST_AND_GET_MOCKED_RESPONSE(
+          {
+            method: options.method ?? "GET",
+            url: _url.href,
+          },
+          {
+            qparam: options.params,
+            auth: options.token,
+            request: options.data,
+          },
+        );
+        const status = mocked.expectedQuery?.query.code ?? 200;
+        const requestPayload = mocked.expectedQuery?.params?.request;
+        const responsePayload = mocked.expectedQuery?.params?.response;
+
+        return {
+          ok: true,
+          data: responsePayload as T,
+          loading: false,
+          clientError: false,
+          serverError: false,
+          info: {
+            hasToken: !!options.token,
+            status,
+            url: _url.href,
+            payload: options.data,
+            options: {},
+          },
+        };
+      }
+      const SC: any = SWRConfig;
+
+      const mockHttpClient = new class implements HttpRequestLibrary {
+        async fetch(url: string, options?: HttpRequestOptions | undefined): 
Promise<HttpResponse> {
+          const _url = new URL(url);
+          const mocked = __SAVE_REQUEST_AND_GET_MOCKED_RESPONSE(
+            {
+              method: options?.method ?? "GET",
+              url: _url.href,
+            },
+            {
+              qparam: _url.searchParams,
+              auth: options as any,
+              request: options?.body as any,
+            },
+          );
+          const status = mocked.expectedQuery?.query.code ?? 200;
+          const requestPayload = mocked.expectedQuery?.params?.request;
+          const responsePayload = mocked.expectedQuery?.params?.response;
+
+          // FIXME: complete this implementation to mock any query
+          const resp: HttpResponse = {
+            requestUrl: _url.href,
+            status: status,
+            headers: {} as any,
+            requestMethod: options?.method ?? "GET",
+            json: async () => responsePayload,
+            text: async () => responsePayload as any as string,
+            bytes: async () => responsePayload as ArrayBuffer,
+          };
+          return resp
+        }
+        get(url: string, opt?: HttpRequestOptions): Promise<HttpResponse> {
+          return this.fetch(url, {
+            method: "GET",
+            ...opt,
+          });
+        }
+
+        postJson(
+          url: string,
+          body: any,
+          opt?: HttpRequestOptions,
+        ): Promise<HttpResponse> {
+          return this.fetch(url, {
+            method: "POST",
+            headers: { "Content-Type": "application/json" },
+            body: JSON.stringify(body),
+            ...opt,
+          });
+        }
+
+      }
+      const bankCore = new TalerCoreBankHttpClient("http://localhost";, 
mockHttpClient)
+      const bankIntegration = bankCore.getIntegrationAPI()
+      const bankRevenue = bankCore.getRevenueAPI("a")
+      const bankWire = bankCore.getWireGatewayAPI("b")
+
+      return (
+        <BackendContextProvider defaultUrl="http://backend";>
+          <InstanceContextProvider
+            value={{
+              token: undefined,
+              id: "default",
+              admin: true,
+              changeToken: () => null,
+            }}
+          >
+            <ApiContextProvider value={{ request, bankCore, bankIntegration, 
bankRevenue, bankWire }}>
+              <SC
+                value={{
+                  loadingTimeout: 0,
+                  dedupingInterval: 0,
+                  shouldRetryOnError: false,
+                  errorRetryInterval: 0,
+                  errorRetryCount: 0,
+                  provider: () => new Map(),
+                }}
+              >
+                {children}
+              </SC>
+            </ApiContextProvider>
+          </InstanceContextProvider>
+        </BackendContextProvider>
+      );
+    };
+  }
+}
diff --git a/packages/auditor-backoffice-ui/src/hooks/transfer.test.ts 
b/packages/auditor-backoffice-ui/src/hooks/transfer.test.ts
new file mode 100644
index 000000000..a7187af27
--- /dev/null
+++ b/packages/auditor-backoffice-ui/src/hooks/transfer.test.ts
@@ -0,0 +1,254 @@
+/*
+ This file is part of GNU Taler
+ (C) 2021-2023 Taler Systems S.A.
+
+ GNU Taler is free software; you can redistribute it and/or modify it under the
+ terms of the GNU General Public License as published by the Free Software
+ Foundation; either version 3, or (at your option) any later version.
+
+ GNU Taler is distributed in the hope that it will be useful, but WITHOUT ANY
+ WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
+ A PARTICULAR PURPOSE.  See the GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License along with
+ GNU Taler; see the file COPYING.  If not, see <http://www.gnu.org/licenses/>
+ */
+
+/**
+ *
+ * @author Sebastian Javier Marchano (sebasjm)
+ */
+
+import * as tests from "@gnu-taler/web-util/testing";
+import { expect } from "chai";
+import { MerchantBackend } from "../declaration.js";
+import { API_INFORM_TRANSFERS, API_LIST_TRANSFERS } from "./urls.js";
+import { ApiMockEnvironment } from "./testing.js";
+import { useInstanceTransfers, useTransferAPI } from "./transfer.js";
+
+describe("transfer api interaction with listing", () => {
+  it("should evict cache when informing a transfer", async () => {
+    const env = new ApiMockEnvironment();
+
+    env.addRequestExpectation(API_LIST_TRANSFERS, {
+      qparam: { limit: -20 },
+      response: {
+        transfers: [{ wtid: "2" } as 
MerchantBackend.Transfers.TransferDetails],
+      },
+    });
+
+    const moveCursor = (d: string) => {
+      console.log("new position", d);
+    };
+
+    const hookBehavior = await tests.hookBehaveLikeThis(
+      () => {
+        const query = useInstanceTransfers({}, moveCursor);
+        const api = useTransferAPI();
+        return { query, api };
+      },
+      {},
+      [
+        ({ query, api }) => {
+          expect(query.loading).true;
+        },
+
+        ({ query, api }) => {
+          expect(env.assertJustExpectedRequestWereMade()).deep.eq({
+            result: "ok",
+          });
+          expect(query.loading).undefined;
+          expect(query.ok).true;
+          if (!query.ok) return;
+          expect(query.data).deep.equals({
+            transfers: [{ wtid: "2" }],
+          });
+
+          env.addRequestExpectation(API_INFORM_TRANSFERS, {
+            request: {
+              wtid: "3",
+              credit_amount: "EUR:1",
+              exchange_url: "exchange.url",
+              payto_uri: "payto://",
+            },
+            response: { total: "" } as any,
+          });
+
+          env.addRequestExpectation(API_LIST_TRANSFERS, {
+            qparam: { limit: -20 },
+            response: {
+              transfers: [{ wtid: "3" } as any, { wtid: "2" } as any],
+            },
+          });
+
+          api.informTransfer({
+            wtid: "3",
+            credit_amount: "EUR:1",
+            exchange_url: "exchange.url",
+            payto_uri: "payto://",
+          });
+        },
+        ({ query, api }) => {
+          expect(env.assertJustExpectedRequestWereMade()).deep.eq({
+            result: "ok",
+          });
+          expect(query.loading).undefined;
+          expect(query.ok).true;
+          if (!query.ok) return;
+
+          expect(query.data).deep.equals({
+            transfers: [{ wtid: "3" }, { wtid: "2" }],
+          });
+        },
+      ],
+      env.buildTestingContext(),
+    );
+
+    expect(hookBehavior).deep.eq({ result: "ok" });
+    expect(env.assertJustExpectedRequestWereMade()).deep.eq({ result: "ok" });
+  });
+});
+
+describe("transfer listing pagination", () => {
+  it("should not load more if has reach the end", async () => {
+    const env = new ApiMockEnvironment();
+
+    env.addRequestExpectation(API_LIST_TRANSFERS, {
+      qparam: { limit: -20, payto_uri: "payto://" },
+      response: {
+        transfers: [{ wtid: "2" }, { wtid: "1" } as any],
+      },
+    });
+
+    const moveCursor = (d: string) => {
+      console.log("new position", d);
+    };
+    const hookBehavior = await tests.hookBehaveLikeThis(
+      () => {
+        return useInstanceTransfers({ payto_uri: "payto://" }, moveCursor);
+      },
+      {},
+      [
+        (query) => {
+          expect(env.assertJustExpectedRequestWereMade()).deep.eq({
+            result: "ok",
+          });
+          expect(query.loading).true;
+        },
+        (query) => {
+          expect(query.loading).undefined;
+          expect(query.ok).true;
+          if (!query.ok) return;
+          expect(query.data).deep.equals({
+            transfers: [{ wtid: "2" }, { wtid: "1" }],
+          });
+          expect(query.isReachingEnd).true;
+          expect(query.isReachingStart).true;
+
+          //check that this button won't trigger more updates since
+          //has reach end and start
+          query.loadMore();
+          query.loadMorePrev();
+        },
+      ],
+      env.buildTestingContext(),
+    );
+
+    expect(env.assertJustExpectedRequestWereMade()).deep.eq({ result: "ok" });
+    expect(hookBehavior).deep.eq({ result: "ok" });
+  });
+
+  it("should load more if result brings more that PAGE_SIZE", async () => {
+    const env = new ApiMockEnvironment();
+
+    const transfersFrom0to20 = Array.from({ length: 20 }).map((e, i) => ({
+      wtid: String(i),
+    }));
+    const transfersFrom20to40 = Array.from({ length: 20 }).map((e, i) => ({
+      wtid: String(i + 20),
+    }));
+    const transfersFrom20to0 = [...transfersFrom0to20].reverse();
+
+    env.addRequestExpectation(API_LIST_TRANSFERS, {
+      qparam: { limit: 20, payto_uri: "payto://", offset: "1" },
+      response: {
+        transfers: transfersFrom0to20,
+      },
+    });
+
+    env.addRequestExpectation(API_LIST_TRANSFERS, {
+      qparam: { limit: -20, payto_uri: "payto://", offset: "1" },
+      response: {
+        transfers: transfersFrom20to40,
+      },
+    });
+
+    const moveCursor = (d: string) => {
+      console.log("new position", d);
+    };
+
+    const hookBehavior = await tests.hookBehaveLikeThis(
+      () => {
+        return useInstanceTransfers(
+          { payto_uri: "payto://", position: "1" },
+          moveCursor,
+        );
+      },
+      {},
+      [
+        (result) => {
+          expect(env.assertJustExpectedRequestWereMade()).deep.eq({
+            result: "ok",
+          });
+          expect(result.loading).true;
+        },
+        (result) => {
+          expect(result.loading).undefined;
+          expect(result.ok).true;
+          if (!result.ok) return;
+          expect(result.data).deep.equals({
+            transfers: [...transfersFrom20to0, ...transfersFrom20to40],
+          });
+          expect(result.isReachingEnd).false;
+          expect(result.isReachingStart).false;
+
+          //query more
+          env.addRequestExpectation(API_LIST_TRANSFERS, {
+            qparam: { limit: -40, payto_uri: "payto://", offset: "1" },
+            response: {
+              transfers: [...transfersFrom20to40, { wtid: "41" }],
+            },
+          });
+          result.loadMore();
+        },
+        (result) => {
+          expect(env.assertJustExpectedRequestWereMade()).deep.eq({
+            result: "ok",
+          });
+          expect(result.loading).true;
+        },
+        (result) => {
+          expect(env.assertJustExpectedRequestWereMade()).deep.eq({
+            result: "ok",
+          });
+          expect(result.loading).undefined;
+          expect(result.ok).true;
+          if (!result.ok) return;
+          expect(result.data).deep.equals({
+            transfers: [
+              ...transfersFrom20to0,
+              ...transfersFrom20to40,
+              { wtid: "41" },
+            ],
+          });
+          expect(result.isReachingEnd).true;
+          expect(result.isReachingStart).false;
+        },
+      ],
+      env.buildTestingContext(),
+    );
+
+    expect(env.assertJustExpectedRequestWereMade()).deep.eq({ result: "ok" });
+    expect(hookBehavior).deep.eq({ result: "ok" });
+  });
+});
diff --git a/packages/auditor-backoffice-ui/src/hooks/transfer.ts 
b/packages/auditor-backoffice-ui/src/hooks/transfer.ts
new file mode 100644
index 000000000..27c3bdc75
--- /dev/null
+++ b/packages/auditor-backoffice-ui/src/hooks/transfer.ts
@@ -0,0 +1,188 @@
+/*
+ This file is part of GNU Taler
+ (C) 2021-2023 Taler Systems S.A.
+
+ GNU Taler is free software; you can redistribute it and/or modify it under the
+ terms of the GNU General Public License as published by the Free Software
+ Foundation; either version 3, or (at your option) any later version.
+
+ GNU Taler is distributed in the hope that it will be useful, but WITHOUT ANY
+ WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
+ A PARTICULAR PURPOSE.  See the GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License along with
+ GNU Taler; see the file COPYING.  If not, see <http://www.gnu.org/licenses/>
+ */
+import {
+  HttpResponse,
+  HttpResponseOk,
+  HttpResponsePaginated,
+  RequestError,
+} from "@gnu-taler/web-util/browser";
+import { useEffect, useState } from "preact/hooks";
+import { MerchantBackend } from "../declaration.js";
+import { MAX_RESULT_SIZE, PAGE_SIZE } from "../utils/constants.js";
+import { useBackendInstanceRequest, useMatchMutate } from "./backend.js";
+
+// FIX default import https://github.com/microsoft/TypeScript/issues/49189
+import _useSWR, { SWRHook } from "swr";
+const useSWR = _useSWR as unknown as SWRHook;
+
+export function useTransferAPI(): TransferAPI {
+  const mutateAll = useMatchMutate();
+  const { request } = useBackendInstanceRequest();
+
+  const informTransfer = async (
+    data: MerchantBackend.Transfers.TransferInformation,
+  ): Promise<HttpResponseOk<{}>> => {
+    const res = await request<{}>(`/private/transfers`, {
+      method: "POST",
+      data,
+    });
+
+    await mutateAll(/.*private\/transfers.*/);
+    return res;
+  };
+
+  return { informTransfer };
+}
+
+export interface TransferAPI {
+  informTransfer: (
+    data: MerchantBackend.Transfers.TransferInformation,
+  ) => Promise<HttpResponseOk<{}>>;
+}
+
+export interface InstanceTransferFilter {
+  payto_uri?: string;
+  verified?: "yes" | "no";
+  position?: string;
+}
+
+export function useInstanceTransfers(
+  args?: InstanceTransferFilter,
+  updatePosition?: (id: string) => void,
+): HttpResponsePaginated<
+  MerchantBackend.Transfers.TransferList,
+  MerchantBackend.ErrorDetail
+> {
+  const { transferFetcher } = useBackendInstanceRequest();
+
+  const [pageBefore, setPageBefore] = useState(1);
+  const [pageAfter, setPageAfter] = useState(1);
+
+  const totalAfter = pageAfter * PAGE_SIZE;
+  const totalBefore = args?.position !== undefined ? pageBefore * PAGE_SIZE : 
0;
+
+  /**
+   * FIXME: this can be cleaned up a little
+   *
+   * the logic of double query should be inside the orderFetch so from the 
hook perspective and cache
+   * is just one query and one error status
+   */
+  const {
+    data: beforeData,
+    error: beforeError,
+    isValidating: loadingBefore,
+  } = useSWR<
+    HttpResponseOk<MerchantBackend.Transfers.TransferList>,
+    RequestError<MerchantBackend.ErrorDetail>
+  >(
+    [
+      `/private/transfers`,
+      args?.payto_uri,
+      args?.verified,
+      args?.position,
+      totalBefore,
+    ],
+    transferFetcher,
+  );
+  const {
+    data: afterData,
+    error: afterError,
+    isValidating: loadingAfter,
+  } = useSWR<
+    HttpResponseOk<MerchantBackend.Transfers.TransferList>,
+    RequestError<MerchantBackend.ErrorDetail>
+  >(
+    [
+      `/private/transfers`,
+      args?.payto_uri,
+      args?.verified,
+      args?.position,
+      -totalAfter,
+    ],
+    transferFetcher,
+  );
+
+  //this will save last result
+  const [lastBefore, setLastBefore] = useState<
+    HttpResponse<
+      MerchantBackend.Transfers.TransferList,
+      MerchantBackend.ErrorDetail
+    >
+  >({ loading: true });
+  const [lastAfter, setLastAfter] = useState<
+    HttpResponse<
+      MerchantBackend.Transfers.TransferList,
+      MerchantBackend.ErrorDetail
+    >
+  >({ loading: true });
+  useEffect(() => {
+    if (afterData) setLastAfter(afterData);
+    if (beforeData) setLastBefore(beforeData);
+  }, [afterData, beforeData]);
+
+  if (beforeError) return beforeError.cause;
+  if (afterError) return afterError.cause;
+
+  // if the query returns less that we ask, then we have reach the end or 
beginning
+  const isReachingEnd =
+    afterData && afterData.data.transfers.length < totalAfter;
+  const isReachingStart =
+    args?.position === undefined ||
+    (beforeData && beforeData.data.transfers.length < totalBefore);
+
+  const pagination = {
+    isReachingEnd,
+    isReachingStart,
+    loadMore: () => {
+      if (!afterData || isReachingEnd) return;
+      if (afterData.data.transfers.length < MAX_RESULT_SIZE) {
+        setPageAfter(pageAfter + 1);
+      } else {
+        const from = `${
+          afterData.data.transfers[afterData.data.transfers.length - 1]
+            .transfer_serial_id
+        }`;
+        if (from && updatePosition) updatePosition(from);
+      }
+    },
+    loadMorePrev: () => {
+      if (!beforeData || isReachingStart) return;
+      if (beforeData.data.transfers.length < MAX_RESULT_SIZE) {
+        setPageBefore(pageBefore + 1);
+      } else if (beforeData) {
+        const from = `${
+          beforeData.data.transfers[beforeData.data.transfers.length - 1]
+            .transfer_serial_id
+        }`;
+        if (from && updatePosition) updatePosition(from);
+      }
+    },
+  };
+
+  const transfers =
+    !beforeData || !afterData
+      ? []
+      : (beforeData || lastBefore).data.transfers
+          .slice()
+          .reverse()
+          .concat((afterData || lastAfter).data.transfers);
+  if (loadingAfter || loadingBefore)
+    return { loading: true, data: { transfers } };
+  if (beforeData && afterData) {
+    return { ok: true, data: { transfers }, ...pagination };
+  }
+  return { loading: true };
+}
diff --git a/packages/auditor-backoffice-ui/src/hooks/urls.ts 
b/packages/auditor-backoffice-ui/src/hooks/urls.ts
new file mode 100644
index 000000000..b6485259f
--- /dev/null
+++ b/packages/auditor-backoffice-ui/src/hooks/urls.ts
@@ -0,0 +1,303 @@
+/*
+ This file is part of GNU Taler
+ (C) 2021-2023 Taler Systems S.A.
+
+ GNU Taler is free software; you can redistribute it and/or modify it under the
+ terms of the GNU General Public License as published by the Free Software
+ Foundation; either version 3, or (at your option) any later version.
+
+ GNU Taler is distributed in the hope that it will be useful, but WITHOUT ANY
+ WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
+ A PARTICULAR PURPOSE.  See the GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License along with
+ GNU Taler; see the file COPYING.  If not, see <http://www.gnu.org/licenses/>
+ */
+
+/**
+ *
+ * @author Sebastian Javier Marchano (sebasjm)
+ */
+import { Query } from "@gnu-taler/web-util/testing";
+import { MerchantBackend } from "../declaration.js";
+
+////////////////////
+// ORDER
+////////////////////
+
+export const API_CREATE_ORDER: Query<
+  MerchantBackend.Orders.PostOrderRequest,
+  MerchantBackend.Orders.PostOrderResponse
+> = {
+  method: "POST",
+  url: "http://backend/instances/default/private/orders";,
+};
+
+export const API_GET_ORDER_BY_ID = (
+  id: string,
+): Query<unknown, MerchantBackend.Orders.MerchantOrderStatusResponse> => ({
+  method: "GET",
+  url: `http://backend/instances/default/private/orders/${id}`,
+});
+
+export const API_LIST_ORDERS: Query<
+  unknown,
+  MerchantBackend.Orders.OrderHistory
+> = {
+  method: "GET",
+  url: "http://backend/instances/default/private/orders";,
+};
+
+export const API_REFUND_ORDER_BY_ID = (
+  id: string,
+): Query<
+  MerchantBackend.Orders.RefundRequest,
+  MerchantBackend.Orders.MerchantRefundResponse
+> => ({
+  method: "POST",
+  url: `http://backend/instances/default/private/orders/${id}/refund`,
+});
+
+export const API_FORGET_ORDER_BY_ID = (
+  id: string,
+): Query<MerchantBackend.Orders.ForgetRequest, unknown> => ({
+  method: "PATCH",
+  url: `http://backend/instances/default/private/orders/${id}/forget`,
+});
+
+export const API_DELETE_ORDER = (
+  id: string,
+): Query<MerchantBackend.Orders.ForgetRequest, unknown> => ({
+  method: "DELETE",
+  url: `http://backend/instances/default/private/orders/${id}`,
+});
+
+////////////////////
+// TRANSFER
+////////////////////
+
+export const API_LIST_TRANSFERS: Query<
+  unknown,
+  MerchantBackend.Transfers.TransferList
+> = {
+  method: "GET",
+  url: "http://backend/instances/default/private/transfers";,
+};
+
+export const API_INFORM_TRANSFERS: Query<
+  MerchantBackend.Transfers.TransferInformation,
+  {}
+> = {
+  method: "POST",
+  url: "http://backend/instances/default/private/transfers";,
+};
+
+////////////////////
+// PRODUCT
+////////////////////
+
+export const API_CREATE_PRODUCT: Query<
+  MerchantBackend.Products.ProductAddDetail,
+  unknown
+> = {
+  method: "POST",
+  url: "http://backend/instances/default/private/products";,
+};
+
+export const API_LIST_PRODUCTS: Query<
+  unknown,
+  MerchantBackend.Products.InventorySummaryResponse
+> = {
+  method: "GET",
+  url: "http://backend/instances/default/private/products";,
+};
+
+export const API_GET_PRODUCT_BY_ID = (
+  id: string,
+): Query<unknown, MerchantBackend.Products.ProductDetail> => ({
+  method: "GET",
+  url: `http://backend/instances/default/private/products/${id}`,
+});
+
+export const API_UPDATE_PRODUCT_BY_ID = (
+  id: string,
+): Query<
+  MerchantBackend.Products.ProductPatchDetail,
+  MerchantBackend.Products.InventorySummaryResponse
+> => ({
+  method: "PATCH",
+  url: `http://backend/instances/default/private/products/${id}`,
+});
+
+export const API_DELETE_PRODUCT = (id: string): Query<unknown, unknown> => ({
+  method: "DELETE",
+  url: `http://backend/instances/default/private/products/${id}`,
+});
+
+////////////////////
+// RESERVES
+////////////////////
+
+export const API_CREATE_RESERVE: Query<
+  MerchantBackend.Rewards.ReserveCreateRequest,
+  MerchantBackend.Rewards.ReserveCreateConfirmation
+> = {
+  method: "POST",
+  url: "http://backend/instances/default/private/reserves";,
+};
+export const API_LIST_RESERVES: Query<
+  unknown,
+  MerchantBackend.Rewards.RewardReserveStatus
+> = {
+  method: "GET",
+  url: "http://backend/instances/default/private/reserves";,
+};
+
+export const API_GET_RESERVE_BY_ID = (
+  pub: string,
+): Query<unknown, MerchantBackend.Rewards.ReserveDetail> => ({
+  method: "GET",
+  url: `http://backend/instances/default/private/reserves/${pub}`,
+});
+
+export const API_GET_REWARD_BY_ID = (
+  pub: string,
+): Query<unknown, MerchantBackend.Rewards.RewardDetails> => ({
+  method: "GET",
+  url: `http://backend/instances/default/private/rewards/${pub}`,
+});
+
+export const API_AUTHORIZE_REWARD_FOR_RESERVE = (
+  pub: string,
+): Query<
+  MerchantBackend.Rewards.RewardCreateRequest,
+  MerchantBackend.Rewards.RewardCreateConfirmation
+> => ({
+  method: "POST",
+  url: 
`http://backend/instances/default/private/reserves/${pub}/authorize-reward`,
+});
+
+export const API_AUTHORIZE_REWARD: Query<
+  MerchantBackend.Rewards.RewardCreateRequest,
+  MerchantBackend.Rewards.RewardCreateConfirmation
+> = {
+  method: "POST",
+  url: `http://backend/instances/default/private/rewards`,
+};
+
+export const API_DELETE_RESERVE = (id: string): Query<unknown, unknown> => ({
+  method: "DELETE",
+  url: `http://backend/instances/default/private/reserves/${id}`,
+});
+
+////////////////////
+// INSTANCE ADMIN
+////////////////////
+
+export const API_CREATE_INSTANCE: Query<
+  MerchantBackend.Instances.InstanceConfigurationMessage,
+  unknown
+> = {
+  method: "POST",
+  url: "http://backend/management/instances";,
+};
+
+export const API_GET_INSTANCE_BY_ID = (
+  id: string,
+): Query<unknown, MerchantBackend.Instances.QueryInstancesResponse> => ({
+  method: "GET",
+  url: `http://backend/management/instances/${id}`,
+});
+
+export const API_GET_INSTANCE_KYC_BY_ID = (
+  id: string,
+): Query<unknown, MerchantBackend.KYC.AccountKycRedirects> => ({
+  method: "GET",
+  url: `http://backend/management/instances/${id}/kyc`,
+});
+
+export const API_LIST_INSTANCES: Query<
+  unknown,
+  MerchantBackend.Instances.InstancesResponse
+> = {
+  method: "GET",
+  url: "http://backend/management/instances";,
+};
+
+export const API_UPDATE_INSTANCE_BY_ID = (
+  id: string,
+): Query<
+  MerchantBackend.Instances.InstanceReconfigurationMessage,
+  unknown
+> => ({
+  method: "PATCH",
+  url: `http://backend/management/instances/${id}`,
+});
+
+export const API_UPDATE_INSTANCE_AUTH_BY_ID = (
+  id: string,
+): Query<
+  MerchantBackend.Instances.InstanceAuthConfigurationMessage,
+  unknown
+> => ({
+  method: "POST",
+  url: `http://backend/management/instances/${id}/auth`,
+});
+
+export const API_DELETE_INSTANCE = (id: string): Query<unknown, unknown> => ({
+  method: "DELETE",
+  url: `http://backend/management/instances/${id}`,
+});
+
+////////////////////
+// AUTH
+////////////////////
+
+export const API_NEW_LOGIN: Query<
+  MerchantBackend.Instances.LoginTokenRequest,
+  unknown
+> = ({
+  method: "POST",
+  url: `http://backend/private/token`,
+});
+
+////////////////////
+// INSTANCE
+////////////////////
+
+export const API_GET_CURRENT_INSTANCE: Query<
+  unknown,
+  MerchantBackend.Instances.QueryInstancesResponse
+> = {
+  method: "GET",
+  url: `http://backend/instances/default/private/`,
+};
+
+export const API_GET_CURRENT_INSTANCE_KYC: Query<
+  unknown,
+  MerchantBackend.KYC.AccountKycRedirects
+> = {
+  method: "GET",
+  url: `http://backend/instances/default/private/kyc`,
+};
+
+export const API_UPDATE_CURRENT_INSTANCE: Query<
+  MerchantBackend.Instances.InstanceReconfigurationMessage,
+  unknown
+> = {
+  method: "PATCH",
+  url: `http://backend/instances/default/private/`,
+};
+
+export const API_UPDATE_CURRENT_INSTANCE_AUTH: Query<
+  MerchantBackend.Instances.InstanceAuthConfigurationMessage,
+  unknown
+> = {
+  method: "POST",
+  url: `http://backend/instances/default/private/auth`,
+};
+
+export const API_DELETE_CURRENT_INSTANCE: Query<unknown, unknown> = {
+  method: "DELETE",
+  url: `http://backend/instances/default/private`,
+};
diff --git a/packages/auditor-backoffice-ui/src/hooks/useSettings.ts 
b/packages/auditor-backoffice-ui/src/hooks/useSettings.ts
new file mode 100644
index 000000000..8c1ebd9f6
--- /dev/null
+++ b/packages/auditor-backoffice-ui/src/hooks/useSettings.ts
@@ -0,0 +1,73 @@
+/*
+ This file is part of GNU Taler
+ (C) 2022 Taler Systems S.A.
+
+ GNU Taler is free software; you can redistribute it and/or modify it under the
+ terms of the GNU General Public License as published by the Free Software
+ Foundation; either version 3, or (at your option) any later version.
+
+ GNU Taler is distributed in the hope that it will be useful, but WITHOUT ANY
+ WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
+ A PARTICULAR PURPOSE.  See the GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License along with
+ GNU Taler; see the file COPYING.  If not, see <http://www.gnu.org/licenses/>
+ */
+
+import { buildStorageKey, useLocalStorage } from "@gnu-taler/web-util/browser";
+import {
+  Codec,
+  buildCodecForObject,
+  codecForBoolean,
+  codecForConstString,
+  codecForEither,
+  codecForString,
+} from "@gnu-taler/taler-util";
+
+export interface Settings {
+  advanceOrderMode: boolean;
+  dateFormat: "ymd" | "dmy" | "mdy";
+}
+
+const defaultSettings: Settings = {
+  advanceOrderMode: false,
+  dateFormat: "ymd",
+}
+
+export const codecForSettings = (): Codec<Settings> =>
+  buildCodecForObject<Settings>()
+    .property("advanceOrderMode", codecForBoolean())
+    .property("dateFormat", codecForEither(
+      codecForConstString("ymd"),
+      codecForConstString("dmy"),
+      codecForConstString("mdy"),
+    ))
+    .build("Settings");
+
+const SETTINGS_KEY = buildStorageKey("merchant-settings", codecForSettings());
+
+export function useSettings(): [
+  Readonly<Settings>,
+  (s: Settings) => void,
+] {
+  const { value, update } = useLocalStorage(SETTINGS_KEY, defaultSettings);
+
+  // const parsed: Settings = value ?? defaultSettings;
+  // function updateField<T extends keyof Settings>(k: T, v: Settings[T]) {
+  //   const next = { ...parsed, [k]: v }
+  //   update(next);
+  // }
+  return [value, update];
+}
+
+export function dateFormatForSettings(s: Settings): string {
+  switch (s.dateFormat) {
+    case "ymd": return "yyyy/MM/dd"
+    case "dmy": return "dd/MM/yyyy"
+    case "mdy": return "MM/dd/yyyy"
+  }
+}
+
+export function datetimeFormatForSettings(s: Settings): string {
+  return dateFormatForSettings(s) + " HH:mm:ss"
+}
\ No newline at end of file
diff --git a/packages/auditor-backoffice-ui/src/hooks/webhooks.ts 
b/packages/auditor-backoffice-ui/src/hooks/webhooks.ts
new file mode 100644
index 000000000..ad6bf96e2
--- /dev/null
+++ b/packages/auditor-backoffice-ui/src/hooks/webhooks.ts
@@ -0,0 +1,178 @@
+/*
+ This file is part of GNU Taler
+ (C) 2021-2023 Taler Systems S.A.
+
+ GNU Taler is free software; you can redistribute it and/or modify it under the
+ terms of the GNU General Public License as published by the Free Software
+ Foundation; either version 3, or (at your option) any later version.
+
+ GNU Taler is distributed in the hope that it will be useful, but WITHOUT ANY
+ WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
+ A PARTICULAR PURPOSE.  See the GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License along with
+ GNU Taler; see the file COPYING.  If not, see <http://www.gnu.org/licenses/>
+ */
+import {
+  HttpResponse,
+  HttpResponseOk,
+  HttpResponsePaginated,
+  RequestError,
+} from "@gnu-taler/web-util/browser";
+import { useEffect, useState } from "preact/hooks";
+import { MerchantBackend } from "../declaration.js";
+import { MAX_RESULT_SIZE, PAGE_SIZE } from "../utils/constants.js";
+import { useBackendInstanceRequest, useMatchMutate } from "./backend.js";
+
+// FIX default import https://github.com/microsoft/TypeScript/issues/49189
+import _useSWR, { SWRHook } from "swr";
+const useSWR = _useSWR as unknown as SWRHook;
+
+export function useWebhookAPI(): WebhookAPI {
+  const mutateAll = useMatchMutate();
+  const { request } = useBackendInstanceRequest();
+
+  const createWebhook = async (
+    data: MerchantBackend.Webhooks.WebhookAddDetails,
+  ): Promise<HttpResponseOk<void>> => {
+    const res = await request<void>(`/private/webhooks`, {
+      method: "POST",
+      data,
+    });
+    await mutateAll(/.*private\/webhooks.*/);
+    return res;
+  };
+
+  const updateWebhook = async (
+    webhookId: string,
+    data: MerchantBackend.Webhooks.WebhookPatchDetails,
+  ): Promise<HttpResponseOk<void>> => {
+    const res = await request<void>(`/private/webhooks/${webhookId}`, {
+      method: "PATCH",
+      data,
+    });
+    await mutateAll(/.*private\/webhooks.*/);
+    return res;
+  };
+
+  const deleteWebhook = async (
+    webhookId: string,
+  ): Promise<HttpResponseOk<void>> => {
+    const res = await request<void>(`/private/webhooks/${webhookId}`, {
+      method: "DELETE",
+    });
+    await mutateAll(/.*private\/webhooks.*/);
+    return res;
+  };
+
+  return { createWebhook, updateWebhook, deleteWebhook };
+}
+
+export interface WebhookAPI {
+  createWebhook: (
+    data: MerchantBackend.Webhooks.WebhookAddDetails,
+  ) => Promise<HttpResponseOk<void>>;
+  updateWebhook: (
+    id: string,
+    data: MerchantBackend.Webhooks.WebhookPatchDetails,
+  ) => Promise<HttpResponseOk<void>>;
+  deleteWebhook: (id: string) => Promise<HttpResponseOk<void>>;
+}
+
+export interface InstanceWebhookFilter {
+  //FIXME: add filter to the webhook list
+  position?: string;
+}
+
+export function useInstanceWebhooks(
+  args?: InstanceWebhookFilter,
+  updatePosition?: (id: string) => void,
+): HttpResponsePaginated<
+  MerchantBackend.Webhooks.WebhookSummaryResponse,
+  MerchantBackend.ErrorDetail
+> {
+  const { webhookFetcher } = useBackendInstanceRequest();
+
+  const [pageBefore, setPageBefore] = useState(1);
+  const [pageAfter, setPageAfter] = useState(1);
+
+  const totalAfter = pageAfter * PAGE_SIZE;
+  const totalBefore = args?.position ? pageBefore * PAGE_SIZE : 0;
+
+  const {
+    data: afterData,
+    error: afterError,
+    isValidating: loadingAfter,
+  } = useSWR<
+    HttpResponseOk<MerchantBackend.Webhooks.WebhookSummaryResponse>,
+    RequestError<MerchantBackend.ErrorDetail>
+  >([`/private/webhooks`, args?.position, -totalAfter], webhookFetcher);
+
+  const [lastAfter, setLastAfter] = useState<
+    HttpResponse<
+      MerchantBackend.Webhooks.WebhookSummaryResponse,
+      MerchantBackend.ErrorDetail
+    >
+  >({ loading: true });
+  useEffect(() => {
+    if (afterData) setLastAfter(afterData);
+  }, [afterData]);
+
+  if (afterError) return afterError.cause;
+
+  const isReachingEnd =
+    afterData && afterData.data.webhooks.length < totalAfter;
+  const isReachingStart = true;
+
+  const pagination = {
+    isReachingEnd,
+    isReachingStart,
+    loadMore: () => {
+      if (!afterData || isReachingEnd) return;
+      if (afterData.data.webhooks.length < MAX_RESULT_SIZE) {
+        setPageAfter(pageAfter + 1);
+      } else {
+        const from = `${
+          afterData.data.webhooks[afterData.data.webhooks.length - 
1].webhook_id
+        }`;
+        if (from && updatePosition) updatePosition(from);
+      }
+    },
+    loadMorePrev: () => {
+      return;
+    },
+  };
+
+  const webhooks = !afterData ? [] : (afterData || lastAfter).data.webhooks;
+
+  if (loadingAfter) return { loading: true, data: { webhooks } };
+  if (afterData) {
+    return { ok: true, data: { webhooks }, ...pagination };
+  }
+  return { loading: true };
+}
+
+export function useWebhookDetails(
+  webhookId: string,
+): HttpResponse<
+  MerchantBackend.Webhooks.WebhookDetails,
+  MerchantBackend.ErrorDetail
+> {
+  const { webhookFetcher } = useBackendInstanceRequest();
+
+  const { data, error, isValidating } = useSWR<
+    HttpResponseOk<MerchantBackend.Webhooks.WebhookDetails>,
+    RequestError<MerchantBackend.ErrorDetail>
+  >([`/private/webhooks/${webhookId}`], webhookFetcher, {
+    refreshInterval: 0,
+    refreshWhenHidden: false,
+    revalidateOnFocus: false,
+    revalidateOnReconnect: false,
+    refreshWhenOffline: false,
+  });
+
+  if (isValidating) return { loading: true, data: data?.data };
+  if (data) return data;
+  if (error) return error.cause;
+  return { loading: true };
+}
diff --git a/packages/auditor-backoffice-ui/src/i18n/de.po 
b/packages/auditor-backoffice-ui/src/i18n/de.po
new file mode 100644
index 000000000..2cf0a7c1c
--- /dev/null
+++ b/packages/auditor-backoffice-ui/src/i18n/de.po
@@ -0,0 +1,2742 @@
+# This file is part of TALER
+# (C) 2016 GNUnet e.V.
+#
+# TALER is free software; you can redistribute it and/or modify it under the
+# terms of the GNU General Public License as published by the Free Software
+# Foundation; either version 3, or (at your option) any later version.
+#
+# TALER is distributed in the hope that it will be useful, but WITHOUT ANY
+# WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
+# A PARTICULAR PURPOSE.  See the GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License along with
+# TALER; see the file COPYING.  If not, see <http://www.gnu.org/licenses/>
+#
+msgid ""
+msgstr ""
+"Project-Id-Version: Taler Wallet\n"
+"Report-Msgid-Bugs-To: taler@gnu.org\n"
+"POT-Creation-Date: 2016-11-23 00:00+0100\n"
+"PO-Revision-Date: 2023-12-04 13:44+0000\n"
+"Last-Translator: Stefan Kügel <skuegel@web.de>\n"
+"Language-Team: German <https://weblate.taler.net/projects/gnu-taler/";
+"merchant-backoffice/de/>\n"
+"Language: de\n"
+"MIME-Version: 1.0\n"
+"Content-Type: text/plain; charset=UTF-8\n"
+"Content-Transfer-Encoding: 8bit\n"
+"Plural-Forms: nplurals=2; plural=n != 1;\n"
+"X-Generator: Weblate 5.2.1\n"
+
+#: src/components/modal/index.tsx:71
+#, c-format
+msgid "Cancel"
+msgstr ""
+
+#: src/components/modal/index.tsx:79
+#, c-format
+msgid "%1$s"
+msgstr ""
+
+#: src/components/modal/index.tsx:84
+#, c-format
+msgid "Close"
+msgstr ""
+
+#: src/components/modal/index.tsx:124
+#, c-format
+msgid "Continue"
+msgstr ""
+
+#: src/components/modal/index.tsx:178
+#, c-format
+msgid "Clear"
+msgstr ""
+
+#: src/components/modal/index.tsx:190
+#, c-format
+msgid "Confirm"
+msgstr ""
+
+#: src/components/modal/index.tsx:296
+#, c-format
+msgid "is not the same as the current access token"
+msgstr ""
+
+#: src/components/modal/index.tsx:299
+#, c-format
+msgid "cannot be empty"
+msgstr ""
+
+#: src/components/modal/index.tsx:301
+#, c-format
+msgid "cannot be the same as the old token"
+msgstr ""
+
+#: src/components/modal/index.tsx:305
+#, c-format
+msgid "is not the same"
+msgstr ""
+
+#: src/components/modal/index.tsx:315
+#, c-format
+msgid "You are updating the access token from instance with id %1$s"
+msgstr ""
+
+#: src/components/modal/index.tsx:331
+#, c-format
+msgid "Old access token"
+msgstr ""
+
+#: src/components/modal/index.tsx:332
+#, c-format
+msgid "access token currently in use"
+msgstr ""
+
+#: src/components/modal/index.tsx:338
+#, c-format
+msgid "New access token"
+msgstr ""
+
+#: src/components/modal/index.tsx:339
+#, c-format
+msgid "next access token to be used"
+msgstr ""
+
+#: src/components/modal/index.tsx:344
+#, c-format
+msgid "Repeat access token"
+msgstr ""
+
+#: src/components/modal/index.tsx:345
+#, c-format
+msgid "confirm the same access token"
+msgstr ""
+
+#: src/components/modal/index.tsx:350
+#, c-format
+msgid "Clearing the access token will mean public access to the instance"
+msgstr ""
+
+#: src/components/modal/index.tsx:377
+#, c-format
+msgid "cannot be the same as the old access token"
+msgstr ""
+
+#: src/components/modal/index.tsx:394
+#, c-format
+msgid "You are setting the access token for the new instance"
+msgstr ""
+
+#: src/components/modal/index.tsx:420
+#, c-format
+msgid ""
+"With external authorization method no check will be done by the merchant "
+"backend"
+msgstr ""
+
+#: src/components/modal/index.tsx:436
+#, c-format
+msgid "Set external authorization"
+msgstr ""
+
+#: src/components/modal/index.tsx:448
+#, c-format
+msgid "Set access token"
+msgstr ""
+
+#: src/components/modal/index.tsx:470
+#, c-format
+msgid "Operation in progress..."
+msgstr ""
+
+#: src/components/modal/index.tsx:479
+#, c-format
+msgid "The operation will be automatically canceled after %1$s seconds"
+msgstr ""
+
+#: src/paths/admin/list/TableActive.tsx:80
+#, c-format
+msgid "Instances"
+msgstr ""
+
+#: src/paths/admin/list/TableActive.tsx:93
+#, c-format
+msgid "Delete"
+msgstr ""
+
+#: src/paths/admin/list/TableActive.tsx:99
+#, c-format
+msgid "add new instance"
+msgstr ""
+
+#: src/paths/admin/list/TableActive.tsx:178
+#, c-format
+msgid "ID"
+msgstr ""
+
+#: src/paths/admin/list/TableActive.tsx:181
+#, c-format
+msgid "Name"
+msgstr ""
+
+#: src/paths/admin/list/TableActive.tsx:220
+#, c-format
+msgid "Edit"
+msgstr ""
+
+#: src/paths/admin/list/TableActive.tsx:237
+#, c-format
+msgid "Purge"
+msgstr ""
+
+#: src/paths/admin/list/TableActive.tsx:261
+#, c-format
+msgid "There is no instances yet, add more pressing the + sign"
+msgstr ""
+
+#: src/paths/admin/list/View.tsx:68
+#, c-format
+msgid "Only show active instances"
+msgstr ""
+
+#: src/paths/admin/list/View.tsx:71
+#, c-format
+msgid "Active"
+msgstr ""
+
+#: src/paths/admin/list/View.tsx:78
+#, c-format
+msgid "Only show deleted instances"
+msgstr ""
+
+#: src/paths/admin/list/View.tsx:81
+#, c-format
+msgid "Deleted"
+msgstr ""
+
+#: src/paths/admin/list/View.tsx:88
+#, c-format
+msgid "Show all instances"
+msgstr ""
+
+#: src/paths/admin/list/View.tsx:91
+#, c-format
+msgid "All"
+msgstr ""
+
+#: src/paths/admin/list/index.tsx:101
+#, c-format
+msgid "Instance \"%1$s\" (ID: %2$s) has been deleted"
+msgstr ""
+
+#: src/paths/admin/list/index.tsx:106
+#, c-format
+msgid "Failed to delete instance"
+msgstr ""
+
+#: src/paths/admin/list/index.tsx:124
+#, c-format
+msgid "Instance '%1$s' (ID: %2$s) has been disabled"
+msgstr ""
+
+#: src/paths/admin/list/index.tsx:129
+#, c-format
+msgid "Failed to purge instance"
+msgstr ""
+
+#: src/paths/instance/kyc/list/ListPage.tsx:41
+#, c-format
+msgid "Pending KYC verification"
+msgstr ""
+
+#: src/paths/instance/kyc/list/ListPage.tsx:66
+#, c-format
+msgid "Timed out"
+msgstr ""
+
+#: src/paths/instance/kyc/list/ListPage.tsx:103
+#, c-format
+msgid "Exchange"
+msgstr ""
+
+#: src/paths/instance/kyc/list/ListPage.tsx:106
+#, c-format
+msgid "Target account"
+msgstr ""
+
+#: src/paths/instance/kyc/list/ListPage.tsx:109
+#, c-format
+msgid "KYC URL"
+msgstr ""
+
+#: src/paths/instance/kyc/list/ListPage.tsx:144
+#, c-format
+msgid "Code"
+msgstr ""
+
+#: src/paths/instance/kyc/list/ListPage.tsx:147
+#, c-format
+msgid "Http Status"
+msgstr ""
+
+#: src/paths/instance/kyc/list/ListPage.tsx:177
+#, c-format
+msgid "No pending kyc verification!"
+msgstr ""
+
+#: src/components/form/InputDate.tsx:123
+#, c-format
+msgid "change value to unknown date"
+msgstr ""
+
+#: src/components/form/InputDate.tsx:124
+#, c-format
+msgid "change value to empty"
+msgstr ""
+
+#: src/components/form/InputDate.tsx:131
+#, c-format
+msgid "clear"
+msgstr ""
+
+#: src/components/form/InputDate.tsx:136
+#, c-format
+msgid "change value to never"
+msgstr ""
+
+#: src/components/form/InputDate.tsx:141
+#, c-format
+msgid "never"
+msgstr ""
+
+#: src/components/form/InputLocation.tsx:29
+#, c-format
+msgid "Country"
+msgstr ""
+
+#: src/components/form/InputLocation.tsx:33
+#, c-format
+msgid "Address"
+msgstr ""
+
+#: src/components/form/InputLocation.tsx:39
+#, c-format
+msgid "Building number"
+msgstr ""
+
+#: src/components/form/InputLocation.tsx:41
+#, c-format
+msgid "Building name"
+msgstr ""
+
+#: src/components/form/InputLocation.tsx:42
+#, c-format
+msgid "Street"
+msgstr ""
+
+#: src/components/form/InputLocation.tsx:43
+#, c-format
+msgid "Post code"
+msgstr ""
+
+#: src/components/form/InputLocation.tsx:44
+#, c-format
+msgid "Town location"
+msgstr ""
+
+#: src/components/form/InputLocation.tsx:45
+#, c-format
+msgid "Town"
+msgstr ""
+
+#: src/components/form/InputLocation.tsx:46
+#, c-format
+msgid "District"
+msgstr ""
+
+#: src/components/form/InputLocation.tsx:49
+#, c-format
+msgid "Country subdivision"
+msgstr ""
+
+#: src/components/form/InputSearchProduct.tsx:66
+#, c-format
+msgid "Product id"
+msgstr ""
+
+#: src/components/form/InputSearchProduct.tsx:69
+#, c-format
+msgid "Description"
+msgstr ""
+
+#: src/components/form/InputSearchProduct.tsx:94
+#, c-format
+msgid "Product"
+msgstr ""
+
+#: src/components/form/InputSearchProduct.tsx:95
+#, c-format
+msgid "search products by it's description or id"
+msgstr ""
+
+#: src/components/form/InputSearchProduct.tsx:151
+#, c-format
+msgid "no products found with that description"
+msgstr ""
+
+#: src/components/product/InventoryProductForm.tsx:56
+#, c-format
+msgid "You must enter a valid product identifier."
+msgstr ""
+
+#: src/components/product/InventoryProductForm.tsx:64
+#, c-format
+msgid "Quantity must be greater than 0!"
+msgstr ""
+
+#: src/components/product/InventoryProductForm.tsx:76
+#, c-format
+msgid ""
+"This quantity exceeds remaining stock. Currently, only %1$s units remain "
+"unreserved in stock."
+msgstr ""
+
+#: src/components/product/InventoryProductForm.tsx:109
+#, c-format
+msgid "Quantity"
+msgstr ""
+
+#: src/components/product/InventoryProductForm.tsx:110
+#, c-format
+msgid "how many products will be added"
+msgstr ""
+
+#: src/components/product/InventoryProductForm.tsx:117
+#, c-format
+msgid "Add from inventory"
+msgstr ""
+
+#: src/components/form/InputImage.tsx:105
+#, c-format
+msgid "Image should be smaller than 1 MB"
+msgstr ""
+
+#: src/components/form/InputImage.tsx:110
+#, c-format
+msgid "Add"
+msgstr ""
+
+#: src/components/form/InputImage.tsx:115
+#, c-format
+msgid "Remove"
+msgstr ""
+
+#: src/components/form/InputTaxes.tsx:113
+#, c-format
+msgid "No taxes configured for this product."
+msgstr ""
+
+#: src/components/form/InputTaxes.tsx:119
+#, c-format
+msgid "Amount"
+msgstr ""
+
+#: src/components/form/InputTaxes.tsx:120
+#, c-format
+msgid ""
+"Taxes can be in currencies that differ from the main currency used by the "
+"merchant."
+msgstr ""
+
+#: src/components/form/InputTaxes.tsx:122
+#, c-format
+msgid ""
+"Enter currency and value separated with a colon, e.g. &quot;USD:2.3&quot;."
+msgstr ""
+
+#: src/components/form/InputTaxes.tsx:131
+#, c-format
+msgid "Legal name of the tax, e.g. VAT or import duties."
+msgstr ""
+
+#: src/components/form/InputTaxes.tsx:137
+#, c-format
+msgid "add tax to the tax list"
+msgstr ""
+
+#: src/components/product/NonInventoryProductForm.tsx:72
+#, c-format
+msgid "describe and add a product that is not in the inventory list"
+msgstr ""
+
+#: src/components/product/NonInventoryProductForm.tsx:75
+#, c-format
+msgid "Add custom product"
+msgstr ""
+
+#: src/components/product/NonInventoryProductForm.tsx:86
+#, c-format
+msgid "Complete information of the product"
+msgstr ""
+
+#: src/components/product/NonInventoryProductForm.tsx:185
+#, c-format
+msgid "Image"
+msgstr ""
+
+#: src/components/product/NonInventoryProductForm.tsx:186
+#, c-format
+msgid "photo of the product"
+msgstr ""
+
+#: src/components/product/NonInventoryProductForm.tsx:192
+#, c-format
+msgid "full product description"
+msgstr ""
+
+#: src/components/product/NonInventoryProductForm.tsx:196
+#, c-format
+msgid "Unit"
+msgstr ""
+
+#: src/components/product/NonInventoryProductForm.tsx:197
+#, c-format
+msgid "name of the product unit"
+msgstr ""
+
+#: src/components/product/NonInventoryProductForm.tsx:201
+#, c-format
+msgid "Price"
+msgstr ""
+
+#: src/components/product/NonInventoryProductForm.tsx:202
+#, c-format
+msgid "amount in the current currency"
+msgstr ""
+
+#: src/components/product/NonInventoryProductForm.tsx:211
+#, c-format
+msgid "Taxes"
+msgstr ""
+
+#: src/components/product/ProductList.tsx:38
+#, c-format
+msgid "image"
+msgstr ""
+
+#: src/components/product/ProductList.tsx:41
+#, c-format
+msgid "description"
+msgstr ""
+
+#: src/components/product/ProductList.tsx:44
+#, c-format
+msgid "quantity"
+msgstr ""
+
+#: src/components/product/ProductList.tsx:47
+#, c-format
+msgid "unit price"
+msgstr ""
+
+#: src/components/product/ProductList.tsx:50
+#, c-format
+msgid "total price"
+msgstr ""
+
+#: src/paths/instance/orders/create/CreatePage.tsx:153
+#, c-format
+msgid "required"
+msgstr ""
+
+#: src/paths/instance/orders/create/CreatePage.tsx:157
+#, c-format
+msgid "not valid"
+msgstr ""
+
+#: src/paths/instance/orders/create/CreatePage.tsx:159
+#, c-format
+msgid "must be greater than 0"
+msgstr ""
+
+#: src/paths/instance/orders/create/CreatePage.tsx:164
+#, c-format
+msgid "not a valid json"
+msgstr ""
+
+#: src/paths/instance/orders/create/CreatePage.tsx:170
+#, c-format
+msgid "should be in the future"
+msgstr ""
+
+#: src/paths/instance/orders/create/CreatePage.tsx:173
+#, c-format
+msgid "refund deadline cannot be before pay deadline"
+msgstr ""
+
+#: src/paths/instance/orders/create/CreatePage.tsx:179
+#, c-format
+msgid "wire transfer deadline cannot be before refund deadline"
+msgstr ""
+
+#: src/paths/instance/orders/create/CreatePage.tsx:190
+#, c-format
+msgid "wire transfer deadline cannot be before pay deadline"
+msgstr ""
+
+#: src/paths/instance/orders/create/CreatePage.tsx:197
+#, c-format
+msgid "should have a refund deadline"
+msgstr ""
+
+#: src/paths/instance/orders/create/CreatePage.tsx:202
+#, c-format
+msgid "auto refund cannot be after refund deadline"
+msgstr ""
+
+#: src/paths/instance/orders/create/CreatePage.tsx:360
+#, c-format
+msgid "Manage products in order"
+msgstr ""
+
+#: src/paths/instance/orders/create/CreatePage.tsx:369
+#, c-format
+msgid "Manage list of products in the order."
+msgstr ""
+
+#: src/paths/instance/orders/create/CreatePage.tsx:391
+#, c-format
+msgid "Remove this product from the order."
+msgstr ""
+
+#: src/paths/instance/orders/create/CreatePage.tsx:415
+#, c-format
+msgid "Total price"
+msgstr ""
+
+#: src/paths/instance/orders/create/CreatePage.tsx:417
+#, c-format
+msgid "total product price added up"
+msgstr ""
+
+#: src/paths/instance/orders/create/CreatePage.tsx:430
+#, c-format
+msgid "Amount to be paid by the customer"
+msgstr ""
+
+#: src/paths/instance/orders/create/CreatePage.tsx:436
+#, c-format
+msgid "Order price"
+msgstr ""
+
+#: src/paths/instance/orders/create/CreatePage.tsx:437
+#, c-format
+msgid "final order price"
+msgstr ""
+
+#: src/paths/instance/orders/create/CreatePage.tsx:444
+#, c-format
+msgid "Summary"
+msgstr ""
+
+#: src/paths/instance/orders/create/CreatePage.tsx:445
+#, c-format
+msgid "Title of the order to be shown to the customer"
+msgstr ""
+
+#: src/paths/instance/orders/create/CreatePage.tsx:450
+#, c-format
+msgid "Shipping and Fulfillment"
+msgstr ""
+
+#: src/paths/instance/orders/create/CreatePage.tsx:455
+#, c-format
+msgid "Delivery date"
+msgstr ""
+
+#: src/paths/instance/orders/create/CreatePage.tsx:456
+#, c-format
+msgid "Deadline for physical delivery assured by the merchant."
+msgstr ""
+
+#: src/paths/instance/orders/create/CreatePage.tsx:461
+#, c-format
+msgid "Location"
+msgstr ""
+
+#: src/paths/instance/orders/create/CreatePage.tsx:462
+#, c-format
+msgid "address where the products will be delivered"
+msgstr ""
+
+#: src/paths/instance/orders/create/CreatePage.tsx:469
+#, c-format
+msgid "Fulfillment URL"
+msgstr ""
+
+#: src/paths/instance/orders/create/CreatePage.tsx:470
+#, c-format
+msgid "URL to which the user will be redirected after successful payment."
+msgstr ""
+
+#: src/paths/instance/orders/create/CreatePage.tsx:476
+#, c-format
+msgid "Taler payment options"
+msgstr ""
+
+#: src/paths/instance/orders/create/CreatePage.tsx:477
+#, c-format
+msgid "Override default Taler payment settings for this order"
+msgstr ""
+
+#: src/paths/instance/orders/create/CreatePage.tsx:481
+#, c-format
+msgid "Payment deadline"
+msgstr ""
+
+#: src/paths/instance/orders/create/CreatePage.tsx:482
+#, c-format
+msgid ""
+"Deadline for the customer to pay for the offer before it expires. Inventory "
+"products will be reserved until this deadline."
+msgstr ""
+
+#: src/paths/instance/orders/create/CreatePage.tsx:486
+#, c-format
+msgid "Refund deadline"
+msgstr ""
+
+#: src/paths/instance/orders/create/CreatePage.tsx:487
+#, c-format
+msgid "Time until which the order can be refunded by the merchant."
+msgstr ""
+
+#: src/paths/instance/orders/create/CreatePage.tsx:491
+#, c-format
+msgid "Wire transfer deadline"
+msgstr ""
+
+#: src/paths/instance/orders/create/CreatePage.tsx:492
+#, c-format
+msgid "Deadline for the exchange to make the wire transfer."
+msgstr ""
+
+#: src/paths/instance/orders/create/CreatePage.tsx:496
+#, c-format
+msgid "Auto-refund deadline"
+msgstr ""
+
+#: src/paths/instance/orders/create/CreatePage.tsx:497
+#, c-format
+msgid ""
+"Time until which the wallet will automatically check for refunds without "
+"user interaction."
+msgstr ""
+
+#: src/paths/instance/orders/create/CreatePage.tsx:502
+#, c-format
+msgid "Maximum deposit fee"
+msgstr ""
+
+#: src/paths/instance/orders/create/CreatePage.tsx:503
+#, c-format
+msgid ""
+"Maximum deposit fees the merchant is willing to cover for this order. Higher "
+"deposit fees must be covered in full by the consumer."
+msgstr ""
+
+#: src/paths/instance/orders/create/CreatePage.tsx:507
+#, c-format
+msgid "Maximum wire fee"
+msgstr ""
+
+#: src/paths/instance/orders/create/CreatePage.tsx:508
+#, c-format
+msgid ""
+"Maximum aggregate wire fees the merchant is willing to cover for this order. "
+"Wire fees exceeding this amount are to be covered by the customers."
+msgstr ""
+
+#: src/paths/instance/orders/create/CreatePage.tsx:512
+#, c-format
+msgid "Wire fee amortization"
+msgstr ""
+
+#: src/paths/instance/orders/create/CreatePage.tsx:513
+#, c-format
+msgid ""
+"Factor by which wire fees exceeding the above threshold are divided to "
+"determine the share of excess wire fees to be paid explicitly by the "
+"consumer."
+msgstr ""
+
+#: src/paths/instance/orders/create/CreatePage.tsx:517
+#, c-format
+msgid "Create token"
+msgstr ""
+
+#: src/paths/instance/orders/create/CreatePage.tsx:518
+#, c-format
+msgid ""
+"Uncheck this option if the merchant backend generated an order ID with "
+"enough entropy to prevent adversarial claims."
+msgstr ""
+
+#: src/paths/instance/orders/create/CreatePage.tsx:522
+#, c-format
+msgid "Minimum age required"
+msgstr ""
+
+#: src/paths/instance/orders/create/CreatePage.tsx:523
+#, c-format
+msgid ""
+"Any value greater than 0 will limit the coins able be used to pay this "
+"contract. If empty the age restriction will be defined by the products"
+msgstr ""
+
+#: src/paths/instance/orders/create/CreatePage.tsx:526
+#, c-format
+msgid "Min age defined by the producs is %1$s"
+msgstr ""
+
+#: src/paths/instance/orders/create/CreatePage.tsx:534
+#, c-format
+msgid "Additional information"
+msgstr ""
+
+#: src/paths/instance/orders/create/CreatePage.tsx:535
+#, c-format
+msgid "Custom information to be included in the contract for this order."
+msgstr ""
+
+#: src/paths/instance/orders/create/CreatePage.tsx:541
+#, c-format
+msgid "You must enter a value in JavaScript Object Notation (JSON)."
+msgstr ""
+
+#: src/components/picker/DurationPicker.tsx:55
+#, c-format
+msgid "days"
+msgstr ""
+
+#: src/components/picker/DurationPicker.tsx:65
+#, c-format
+msgid "hours"
+msgstr ""
+
+#: src/components/picker/DurationPicker.tsx:76
+#, c-format
+msgid "minutes"
+msgstr ""
+
+#: src/components/picker/DurationPicker.tsx:87
+#, c-format
+msgid "seconds"
+msgstr ""
+
+#: src/components/form/InputDuration.tsx:53
+#, c-format
+msgid "forever"
+msgstr ""
+
+#: src/components/form/InputDuration.tsx:62
+#, c-format
+msgid "%1$sM"
+msgstr ""
+
+#: src/components/form/InputDuration.tsx:64
+#, c-format
+msgid "%1$sY"
+msgstr ""
+
+#: src/components/form/InputDuration.tsx:66
+#, c-format
+msgid "%1$sd"
+msgstr ""
+
+#: src/components/form/InputDuration.tsx:68
+#, c-format
+msgid "%1$sh"
+msgstr ""
+
+#: src/components/form/InputDuration.tsx:70
+#, c-format
+msgid "%1$smin"
+msgstr ""
+
+#: src/components/form/InputDuration.tsx:72
+#, c-format
+msgid "%1$ssec"
+msgstr ""
+
+#: src/paths/instance/orders/list/Table.tsx:75
+#, c-format
+msgid "Orders"
+msgstr ""
+
+#: src/paths/instance/orders/list/Table.tsx:81
+#, c-format
+msgid "create order"
+msgstr ""
+
+#: src/paths/instance/orders/list/Table.tsx:147
+#, c-format
+msgid "load newer orders"
+msgstr ""
+
+#: src/paths/instance/orders/list/Table.tsx:154
+#, c-format
+msgid "Date"
+msgstr ""
+
+#: src/paths/instance/orders/list/Table.tsx:200
+#, c-format
+msgid "Refund"
+msgstr ""
+
+#: src/paths/instance/orders/list/Table.tsx:209
+#, c-format
+msgid "copy url"
+msgstr ""
+
+#: src/paths/instance/orders/list/Table.tsx:225
+#, c-format
+msgid "load older orders"
+msgstr ""
+
+#: src/paths/instance/orders/list/Table.tsx:242
+#, c-format
+msgid "No orders have been found matching your query!"
+msgstr ""
+
+#: src/paths/instance/orders/list/Table.tsx:288
+#, c-format
+msgid "duplicated"
+msgstr ""
+
+#: src/paths/instance/orders/list/Table.tsx:299
+#, c-format
+msgid "invalid format"
+msgstr ""
+
+#: src/paths/instance/orders/list/Table.tsx:301
+#, c-format
+msgid "this value exceed the refundable amount"
+msgstr ""
+
+#: src/paths/instance/orders/list/Table.tsx:346
+#, c-format
+msgid "date"
+msgstr ""
+
+#: src/paths/instance/orders/list/Table.tsx:349
+#, c-format
+msgid "amount"
+msgstr ""
+
+#: src/paths/instance/orders/list/Table.tsx:352
+#, c-format
+msgid "reason"
+msgstr ""
+
+#: src/paths/instance/orders/list/Table.tsx:389
+#, c-format
+msgid "amount to be refunded"
+msgstr ""
+
+#: src/paths/instance/orders/list/Table.tsx:391
+#, c-format
+msgid "Max refundable:"
+msgstr ""
+
+#: src/paths/instance/orders/list/Table.tsx:396
+#, c-format
+msgid "Reason"
+msgstr ""
+
+#: src/paths/instance/orders/list/Table.tsx:397
+#, c-format
+msgid "Choose one..."
+msgstr ""
+
+#: src/paths/instance/orders/list/Table.tsx:399
+#, c-format
+msgid "requested by the customer"
+msgstr ""
+
+#: src/paths/instance/orders/list/Table.tsx:400
+#, c-format
+msgid "other"
+msgstr ""
+
+#: src/paths/instance/orders/list/Table.tsx:403
+#, c-format
+msgid "why this order is being refunded"
+msgstr ""
+
+#: src/paths/instance/orders/list/Table.tsx:409
+#, c-format
+msgid "more information to give context"
+msgstr ""
+
+#: src/paths/instance/orders/details/DetailPage.tsx:62
+#, c-format
+msgid "Contract Terms"
+msgstr ""
+
+#: src/paths/instance/orders/details/DetailPage.tsx:68
+#, c-format
+msgid "human-readable description of the whole purchase"
+msgstr ""
+
+#: src/paths/instance/orders/details/DetailPage.tsx:74
+#, c-format
+msgid "total price for the transaction"
+msgstr ""
+
+#: src/paths/instance/orders/details/DetailPage.tsx:81
+#, c-format
+msgid "URL for this purchase"
+msgstr ""
+
+#: src/paths/instance/orders/details/DetailPage.tsx:87
+#, c-format
+msgid "Max fee"
+msgstr ""
+
+#: src/paths/instance/orders/details/DetailPage.tsx:88
+#, c-format
+msgid "maximum total deposit fee accepted by the merchant for this contract"
+msgstr ""
+
+#: src/paths/instance/orders/details/DetailPage.tsx:93
+#, c-format
+msgid "Max wire fee"
+msgstr ""
+
+#: src/paths/instance/orders/details/DetailPage.tsx:94
+#, c-format
+msgid "maximum wire fee accepted by the merchant"
+msgstr ""
+
+#: src/paths/instance/orders/details/DetailPage.tsx:100
+#, c-format
+msgid ""
+"over how many customer transactions does the merchant expect to amortize "
+"wire fees on average"
+msgstr ""
+
+#: src/paths/instance/orders/details/DetailPage.tsx:105
+#, c-format
+msgid "Created at"
+msgstr ""
+
+#: src/paths/instance/orders/details/DetailPage.tsx:106
+#, c-format
+msgid "time when this contract was generated"
+msgstr ""
+
+#: src/paths/instance/orders/details/DetailPage.tsx:112
+#, c-format
+msgid "after this deadline has passed no refunds will be accepted"
+msgstr ""
+
+#: src/paths/instance/orders/details/DetailPage.tsx:118
+#, c-format
+msgid ""
+"after this deadline, the merchant won't accept payments for the contract"
+msgstr ""
+
+#: src/paths/instance/orders/details/DetailPage.tsx:124
+#, c-format
+msgid "transfer deadline for the exchange"
+msgstr ""
+
+#: src/paths/instance/orders/details/DetailPage.tsx:130
+#, c-format
+msgid "time indicating when the order should be delivered"
+msgstr ""
+
+#: src/paths/instance/orders/details/DetailPage.tsx:136
+#, c-format
+msgid "where the order will be delivered"
+msgstr ""
+
+#: src/paths/instance/orders/details/DetailPage.tsx:144
+#, c-format
+msgid "Auto-refund delay"
+msgstr ""
+
+#: src/paths/instance/orders/details/DetailPage.tsx:145
+#, c-format
+msgid ""
+"how long the wallet should try to get an automatic refund for the purchase"
+msgstr ""
+
+#: src/paths/instance/orders/details/DetailPage.tsx:150
+#, c-format
+msgid "Extra info"
+msgstr ""
+
+#: src/paths/instance/orders/details/DetailPage.tsx:151
+#, c-format
+msgid "extra data that is only interpreted by the merchant frontend"
+msgstr ""
+
+#: src/paths/instance/orders/details/DetailPage.tsx:219
+#, c-format
+msgid "Order"
+msgstr ""
+
+#: src/paths/instance/orders/details/DetailPage.tsx:221
+#, c-format
+msgid "claimed"
+msgstr ""
+
+#: src/paths/instance/orders/details/DetailPage.tsx:247
+#, c-format
+msgid "claimed at"
+msgstr ""
+
+#: src/paths/instance/orders/details/DetailPage.tsx:265
+#, c-format
+msgid "Timeline"
+msgstr ""
+
+#: src/paths/instance/orders/details/DetailPage.tsx:271
+#, c-format
+msgid "Payment details"
+msgstr ""
+
+#: src/paths/instance/orders/details/DetailPage.tsx:291
+#, c-format
+msgid "Order status"
+msgstr ""
+
+#: src/paths/instance/orders/details/DetailPage.tsx:301
+#, c-format
+msgid "Product list"
+msgstr ""
+
+#: src/paths/instance/orders/details/DetailPage.tsx:451
+#, c-format
+msgid "paid"
+msgstr ""
+
+#: src/paths/instance/orders/details/DetailPage.tsx:455
+#, c-format
+msgid "wired"
+msgstr ""
+
+#: src/paths/instance/orders/details/DetailPage.tsx:460
+#, c-format
+msgid "refunded"
+msgstr ""
+
+#: src/paths/instance/orders/details/DetailPage.tsx:480
+#, c-format
+msgid "refund order"
+msgstr ""
+
+#: src/paths/instance/orders/details/DetailPage.tsx:481
+#, c-format
+msgid "not refundable"
+msgstr ""
+
+#: src/paths/instance/orders/details/DetailPage.tsx:489
+#, c-format
+msgid "refund"
+msgstr ""
+
+#: src/paths/instance/orders/details/DetailPage.tsx:553
+#, c-format
+msgid "Refunded amount"
+msgstr ""
+
+#: src/paths/instance/orders/details/DetailPage.tsx:560
+#, c-format
+msgid "Refund taken"
+msgstr ""
+
+#: src/paths/instance/orders/details/DetailPage.tsx:570
+#, c-format
+msgid "Status URL"
+msgstr ""
+
+#: src/paths/instance/orders/details/DetailPage.tsx:583
+#, c-format
+msgid "Refund URI"
+msgstr ""
+
+#: src/paths/instance/orders/details/DetailPage.tsx:636
+#, c-format
+msgid "unpaid"
+msgstr ""
+
+#: src/paths/instance/orders/details/DetailPage.tsx:654
+#, c-format
+msgid "pay at"
+msgstr ""
+
+#: src/paths/instance/orders/details/DetailPage.tsx:666
+#, c-format
+msgid "created at"
+msgstr ""
+
+#: src/paths/instance/orders/details/DetailPage.tsx:707
+#, c-format
+msgid "Order status URL"
+msgstr ""
+
+#: src/paths/instance/orders/details/DetailPage.tsx:711
+#, c-format
+msgid "Payment URI"
+msgstr ""
+
+#: src/paths/instance/orders/details/DetailPage.tsx:740
+#, c-format
+msgid ""
+"Unknown order status. This is an error, please contact the administrator."
+msgstr ""
+
+#: src/paths/instance/orders/details/DetailPage.tsx:767
+#, c-format
+msgid "Back"
+msgstr "Zurück"
+
+#: src/paths/instance/orders/details/index.tsx:79
+#, c-format
+msgid "refund created successfully"
+msgstr ""
+
+#: src/paths/instance/orders/details/index.tsx:85
+#, c-format
+msgid "could not create the refund"
+msgstr ""
+
+#: src/paths/instance/orders/list/ListPage.tsx:78
+#, c-format
+msgid "select date to show nearby orders"
+msgstr ""
+
+#: src/paths/instance/orders/list/ListPage.tsx:94
+#, c-format
+msgid "order id"
+msgstr ""
+
+#: src/paths/instance/orders/list/ListPage.tsx:100
+#, c-format
+msgid "jump to order with the given order ID"
+msgstr ""
+
+#: src/paths/instance/orders/list/ListPage.tsx:122
+#, c-format
+msgid "remove all filters"
+msgstr ""
+
+#: src/paths/instance/orders/list/ListPage.tsx:132
+#, c-format
+msgid "only show paid orders"
+msgstr ""
+
+#: src/paths/instance/orders/list/ListPage.tsx:135
+#, c-format
+msgid "Paid"
+msgstr ""
+
+#: src/paths/instance/orders/list/ListPage.tsx:142
+#, c-format
+msgid "only show orders with refunds"
+msgstr ""
+
+#: src/paths/instance/orders/list/ListPage.tsx:145
+#, c-format
+msgid "Refunded"
+msgstr "Rückerstattet"
+
+#: src/paths/instance/orders/list/ListPage.tsx:152
+#, c-format
+msgid ""
+"only show orders where customers paid, but wire payments from payment "
+"provider are still pending"
+msgstr ""
+
+#: src/paths/instance/orders/list/ListPage.tsx:155
+#, c-format
+msgid "Not wired"
+msgstr ""
+
+#: src/paths/instance/orders/list/ListPage.tsx:170
+#, c-format
+msgid "clear date filter"
+msgstr ""
+
+#: src/paths/instance/orders/list/ListPage.tsx:184
+#, c-format
+msgid "date (YYYY/MM/DD)"
+msgstr ""
+
+#: src/paths/instance/orders/list/index.tsx:103
+#, c-format
+msgid "Enter an order id"
+msgstr ""
+
+#: src/paths/instance/orders/list/index.tsx:111
+#, c-format
+msgid "order not found"
+msgstr ""
+
+#: src/paths/instance/orders/list/index.tsx:178
+#, c-format
+msgid "could not get the order to refund"
+msgstr ""
+
+#: src/components/exception/AsyncButton.tsx:43
+#, c-format
+msgid "Loading..."
+msgstr ""
+
+#: src/components/form/InputStock.tsx:99
+#, c-format
+msgid ""
+"click here to configure the stock of the product, leave it as is and the "
+"backend will not control stock"
+msgstr ""
+
+#: src/components/form/InputStock.tsx:109
+#, c-format
+msgid "Manage stock"
+msgstr ""
+
+#: src/components/form/InputStock.tsx:115
+#, c-format
+msgid "this product has been configured without stock control"
+msgstr ""
+
+#: src/components/form/InputStock.tsx:119
+#, c-format
+msgid "Infinite"
+msgstr ""
+
+#: src/components/form/InputStock.tsx:136
+#, c-format
+msgid "lost cannot be greater than current and incoming (max %1$s)"
+msgstr ""
+
+#: src/components/form/InputStock.tsx:176
+#, c-format
+msgid "Incoming"
+msgstr ""
+
+#: src/components/form/InputStock.tsx:177
+#, c-format
+msgid "Lost"
+msgstr ""
+
+#: src/components/form/InputStock.tsx:192
+#, c-format
+msgid "Current"
+msgstr ""
+
+#: src/components/form/InputStock.tsx:196
+#, c-format
+msgid "remove stock control for this product"
+msgstr ""
+
+#: src/components/form/InputStock.tsx:202
+#, c-format
+msgid "without stock"
+msgstr ""
+
+#: src/components/form/InputStock.tsx:211
+#, c-format
+msgid "Next restock"
+msgstr ""
+
+#: src/components/form/InputStock.tsx:217
+#, c-format
+msgid "Delivery address"
+msgstr ""
+
+#: src/components/product/ProductForm.tsx:133
+#, c-format
+msgid "product identification to use in URLs (for internal use only)"
+msgstr ""
+
+#: src/components/product/ProductForm.tsx:139
+#, c-format
+msgid "illustration of the product for customers"
+msgstr ""
+
+#: src/components/product/ProductForm.tsx:145
+#, c-format
+msgid "product description for customers"
+msgstr ""
+
+#: src/components/product/ProductForm.tsx:149
+#, c-format
+msgid "Age restricted"
+msgstr ""
+
+#: src/components/product/ProductForm.tsx:150
+#, c-format
+msgid "is this product restricted for customer below certain age?"
+msgstr ""
+
+#: src/components/product/ProductForm.tsx:155
+#, c-format
+msgid ""
+"unit describing quantity of product sold (e.g. 2 kilograms, 5 liters, 3 "
+"items, 5 meters) for customers"
+msgstr ""
+
+#: src/components/product/ProductForm.tsx:160
+#, c-format
+msgid ""
+"sale price for customers, including taxes, for above units of the product"
+msgstr ""
+
+#: src/components/product/ProductForm.tsx:164
+#, c-format
+msgid "Stock"
+msgstr ""
+
+#: src/components/product/ProductForm.tsx:166
+#, c-format
+msgid ""
+"product inventory for products with finite supply (for internal use only)"
+msgstr ""
+
+#: src/components/product/ProductForm.tsx:171
+#, c-format
+msgid "taxes included in the product price, exposed to customers"
+msgstr ""
+
+#: src/paths/instance/products/create/CreatePage.tsx:66
+#, c-format
+msgid "Need to complete marked fields"
+msgstr ""
+
+#: src/paths/instance/products/create/index.tsx:51
+#, c-format
+msgid "could not create product"
+msgstr ""
+
+#: src/paths/instance/products/list/Table.tsx:68
+#, c-format
+msgid "Products"
+msgstr ""
+
+#: src/paths/instance/products/list/Table.tsx:73
+#, c-format
+msgid "add product to inventory"
+msgstr ""
+
+#: src/paths/instance/products/list/Table.tsx:137
+#, c-format
+msgid "Sell"
+msgstr ""
+
+#: src/paths/instance/products/list/Table.tsx:143
+#, c-format
+msgid "Profit"
+msgstr ""
+
+#: src/paths/instance/products/list/Table.tsx:149
+#, c-format
+msgid "Sold"
+msgstr ""
+
+#: src/paths/instance/products/list/Table.tsx:210
+#, c-format
+msgid "free"
+msgstr ""
+
+#: src/paths/instance/products/list/Table.tsx:248
+#, c-format
+msgid "go to product update page"
+msgstr ""
+
+#: src/paths/instance/products/list/Table.tsx:255
+#, c-format
+msgid "Update"
+msgstr ""
+
+#: src/paths/instance/products/list/Table.tsx:260
+#, c-format
+msgid "remove this product from the database"
+msgstr ""
+
+#: src/paths/instance/products/list/Table.tsx:331
+#, c-format
+msgid "update the product with new price"
+msgstr ""
+
+#: src/paths/instance/products/list/Table.tsx:341
+#, c-format
+msgid "update product with new price"
+msgstr ""
+
+#: src/paths/instance/products/list/Table.tsx:399
+#, c-format
+msgid "add more elements to the inventory"
+msgstr ""
+
+#: src/paths/instance/products/list/Table.tsx:404
+#, c-format
+msgid "report elements lost in the inventory"
+msgstr ""
+
+#: src/paths/instance/products/list/Table.tsx:409
+#, c-format
+msgid "new price for the product"
+msgstr ""
+
+#: src/paths/instance/products/list/Table.tsx:421
+#, c-format
+msgid "the are value with errors"
+msgstr ""
+
+#: src/paths/instance/products/list/Table.tsx:422
+#, c-format
+msgid "update product with new stock and price"
+msgstr ""
+
+#: src/paths/instance/products/list/Table.tsx:463
+#, c-format
+msgid "There is no products yet, add more pressing the + sign"
+msgstr ""
+
+#: src/paths/instance/products/list/index.tsx:86
+#, c-format
+msgid "product updated successfully"
+msgstr ""
+
+#: src/paths/instance/products/list/index.tsx:92
+#, c-format
+msgid "could not update the product"
+msgstr ""
+
+#: src/paths/instance/products/list/index.tsx:103
+#, c-format
+msgid "product delete successfully"
+msgstr ""
+
+#: src/paths/instance/products/list/index.tsx:109
+#, c-format
+msgid "could not delete the product"
+msgstr ""
+
+#: src/paths/instance/products/update/UpdatePage.tsx:56
+#, c-format
+msgid "Product id:"
+msgstr ""
+
+#: src/paths/instance/reserves/create/CreatedSuccessfully.tsx:95
+#, c-format
+msgid ""
+"To complete the setup of the reserve, you must now initiate a wire transfer "
+"using the given wire transfer subject and crediting the specified amount to "
+"the indicated account of the exchange."
+msgstr ""
+
+#: src/paths/instance/reserves/create/CreatedSuccessfully.tsx:102
+#, c-format
+msgid "If your system supports RFC 8905, you can do this by opening this URI:"
+msgstr ""
+
+#: src/paths/instance/reserves/create/CreatePage.tsx:83
+#, c-format
+msgid "it should be greater than 0"
+msgstr ""
+
+#: src/paths/instance/reserves/create/CreatePage.tsx:88
+#, c-format
+msgid "must be a valid URL"
+msgstr ""
+
+#: src/paths/instance/reserves/create/CreatePage.tsx:107
+#, c-format
+msgid "Initial balance"
+msgstr ""
+
+#: src/paths/instance/reserves/create/CreatePage.tsx:108
+#, c-format
+msgid "balance prior to deposit"
+msgstr ""
+
+#: src/paths/instance/reserves/create/CreatePage.tsx:112
+#, c-format
+msgid "Exchange URL"
+msgstr ""
+
+#: src/paths/instance/reserves/create/CreatePage.tsx:113
+#, c-format
+msgid "URL of exchange"
+msgstr ""
+
+#: src/paths/instance/reserves/create/CreatePage.tsx:148
+#, c-format
+msgid "Next"
+msgstr ""
+
+#: src/paths/instance/reserves/create/CreatePage.tsx:186
+#, c-format
+msgid "Wire method"
+msgstr ""
+
+#: src/paths/instance/reserves/create/CreatePage.tsx:187
+#, c-format
+msgid "method to use for wire transfer"
+msgstr ""
+
+#: src/paths/instance/reserves/create/CreatePage.tsx:189
+#, c-format
+msgid "Select one wire method"
+msgstr ""
+
+#: src/paths/instance/reserves/create/index.tsx:62
+#, c-format
+msgid "could not create reserve"
+msgstr ""
+
+#: src/paths/instance/reserves/details/DetailPage.tsx:77
+#, c-format
+msgid "Valid until"
+msgstr ""
+
+#: src/paths/instance/reserves/details/DetailPage.tsx:82
+#, c-format
+msgid "Created balance"
+msgstr ""
+
+#: src/paths/instance/reserves/details/DetailPage.tsx:99
+#, c-format
+msgid "Exchange balance"
+msgstr ""
+
+#: src/paths/instance/reserves/details/DetailPage.tsx:104
+#, c-format
+msgid "Picked up"
+msgstr ""
+
+#: src/paths/instance/reserves/details/DetailPage.tsx:109
+#, c-format
+msgid "Committed"
+msgstr ""
+
+#: src/paths/instance/reserves/details/DetailPage.tsx:116
+#, c-format
+msgid "Account address"
+msgstr ""
+
+#: src/paths/instance/reserves/details/DetailPage.tsx:119
+#, c-format
+msgid "Subject"
+msgstr ""
+
+#: src/paths/instance/reserves/details/DetailPage.tsx:130
+#, c-format
+msgid "Tips"
+msgstr ""
+
+#: src/paths/instance/reserves/details/DetailPage.tsx:193
+#, c-format
+msgid "No tips has been authorized from this reserve"
+msgstr ""
+
+#: src/paths/instance/reserves/details/DetailPage.tsx:213
+#, c-format
+msgid "Authorized"
+msgstr ""
+
+#: src/paths/instance/reserves/details/DetailPage.tsx:222
+#, c-format
+msgid "Expiration"
+msgstr ""
+
+#: src/paths/instance/reserves/list/AutorizeTipModal.tsx:108
+#, c-format
+msgid "amount of tip"
+msgstr ""
+
+#: src/paths/instance/reserves/list/AutorizeTipModal.tsx:112
+#, c-format
+msgid "Justification"
+msgstr ""
+
+#: src/paths/instance/reserves/list/AutorizeTipModal.tsx:114
+#, c-format
+msgid "reason for the tip"
+msgstr ""
+
+#: src/paths/instance/reserves/list/AutorizeTipModal.tsx:118
+#, c-format
+msgid "URL after tip"
+msgstr ""
+
+#: src/paths/instance/reserves/list/AutorizeTipModal.tsx:119
+#, c-format
+msgid "URL to visit after tip payment"
+msgstr ""
+
+#: src/paths/instance/reserves/list/Table.tsx:65
+#, c-format
+msgid "Reserves not yet funded"
+msgstr ""
+
+#: src/paths/instance/reserves/list/Table.tsx:89
+#, c-format
+msgid "Reserves ready"
+msgstr ""
+
+#: src/paths/instance/reserves/list/Table.tsx:95
+#, c-format
+msgid "add new reserve"
+msgstr ""
+
+#: src/paths/instance/reserves/list/Table.tsx:143
+#, c-format
+msgid "Expires at"
+msgstr ""
+
+#: src/paths/instance/reserves/list/Table.tsx:146
+#, c-format
+msgid "Initial"
+msgstr ""
+
+#: src/paths/instance/reserves/list/Table.tsx:202
+#, c-format
+msgid "delete selected reserve from the database"
+msgstr ""
+
+#: src/paths/instance/reserves/list/Table.tsx:210
+#, c-format
+msgid "authorize new tip from selected reserve"
+msgstr ""
+
+#: src/paths/instance/reserves/list/Table.tsx:237
+#, c-format
+msgid ""
+"There is no ready reserves yet, add more pressing the + sign or fund them"
+msgstr ""
+
+#: src/paths/instance/reserves/list/Table.tsx:264
+#, c-format
+msgid "Expected Balance"
+msgstr ""
+
+#: src/paths/instance/reserves/list/index.tsx:110
+#, c-format
+msgid "could not create the tip"
+msgstr ""
+
+#: src/paths/instance/templates/create/CreatePage.tsx:77
+#, c-format
+msgid "should not be empty"
+msgstr ""
+
+#: src/paths/instance/templates/create/CreatePage.tsx:93
+#, c-format
+msgid "should be greater that 0"
+msgstr ""
+
+#: src/paths/instance/templates/create/CreatePage.tsx:96
+#, c-format
+msgid "can't be empty"
+msgstr ""
+
+#: src/paths/instance/templates/create/CreatePage.tsx:100
+#, c-format
+msgid "to short"
+msgstr ""
+
+#: src/paths/instance/templates/create/CreatePage.tsx:108
+#, c-format
+msgid "just letters and numbers from 2 to 7"
+msgstr ""
+
+#: src/paths/instance/templates/create/CreatePage.tsx:110
+#, c-format
+msgid "size of the key should be 32"
+msgstr ""
+
+#: src/paths/instance/templates/create/CreatePage.tsx:137
+#, c-format
+msgid "Identifier"
+msgstr ""
+
+#: src/paths/instance/templates/create/CreatePage.tsx:138
+#, c-format
+msgid "Name of the template in URLs."
+msgstr ""
+
+#: src/paths/instance/templates/create/CreatePage.tsx:144
+#, c-format
+msgid "Describe what this template stands for"
+msgstr ""
+
+#: src/paths/instance/templates/create/CreatePage.tsx:149
+#, c-format
+msgid "Fixed summary"
+msgstr ""
+
+#: src/paths/instance/templates/create/CreatePage.tsx:150
+#, c-format
+msgid "If specified, this template will create order with the same summary"
+msgstr ""
+
+#: src/paths/instance/templates/create/CreatePage.tsx:154
+#, c-format
+msgid "Fixed price"
+msgstr ""
+
+#: src/paths/instance/templates/create/CreatePage.tsx:155
+#, c-format
+msgid "If specified, this template will create order with the same price"
+msgstr ""
+
+#: src/paths/instance/templates/create/CreatePage.tsx:159
+#, c-format
+msgid "Minimum age"
+msgstr ""
+
+#: src/paths/instance/templates/create/CreatePage.tsx:161
+#, c-format
+msgid "Is this contract restricted to some age?"
+msgstr ""
+
+#: src/paths/instance/templates/create/CreatePage.tsx:165
+#, c-format
+msgid "Payment timeout"
+msgstr ""
+
+#: src/paths/instance/templates/create/CreatePage.tsx:167
+#, c-format
+msgid ""
+"How much time has the customer to complete the payment once the order was "
+"created."
+msgstr ""
+
+#: src/paths/instance/templates/create/CreatePage.tsx:171
+#, c-format
+msgid "Verification algorithm"
+msgstr ""
+
+#: src/paths/instance/templates/create/CreatePage.tsx:172
+#, c-format
+msgid "Algorithm to use to verify transaction in offline mode"
+msgstr ""
+
+#: src/paths/instance/templates/create/CreatePage.tsx:180
+#, c-format
+msgid "Point-of-sale key"
+msgstr ""
+
+#: src/paths/instance/templates/create/CreatePage.tsx:182
+#, c-format
+msgid "Useful to validate the purchase"
+msgstr ""
+
+#: src/paths/instance/templates/create/CreatePage.tsx:196
+#, c-format
+msgid "generate random secret key"
+msgstr ""
+
+#: src/paths/instance/templates/create/CreatePage.tsx:203
+#, c-format
+msgid "random"
+msgstr ""
+
+#: src/paths/instance/templates/create/CreatePage.tsx:208
+#, c-format
+msgid "show secret key"
+msgstr ""
+
+#: src/paths/instance/templates/create/CreatePage.tsx:209
+#, c-format
+msgid "hide secret key"
+msgstr ""
+
+#: src/paths/instance/templates/create/CreatePage.tsx:216
+#, c-format
+msgid "hide"
+msgstr ""
+
+#: src/paths/instance/templates/create/CreatePage.tsx:218
+#, c-format
+msgid "show"
+msgstr ""
+
+#: src/paths/instance/templates/create/index.tsx:52
+#, c-format
+msgid "could not inform template"
+msgstr ""
+
+#: src/paths/instance/templates/use/UsePage.tsx:54
+#, c-format
+msgid "Amount is required"
+msgstr ""
+
+#: src/paths/instance/templates/use/UsePage.tsx:58
+#, c-format
+msgid "Order summary is required"
+msgstr ""
+
+#: src/paths/instance/templates/use/UsePage.tsx:86
+#, c-format
+msgid "New order for template"
+msgstr ""
+
+#: src/paths/instance/templates/use/UsePage.tsx:108
+#, c-format
+msgid "Amount of the order"
+msgstr ""
+
+#: src/paths/instance/templates/use/UsePage.tsx:113
+#, c-format
+msgid "Order summary"
+msgstr ""
+
+#: src/paths/instance/templates/use/index.tsx:92
+#, c-format
+msgid "could not create order from template"
+msgstr ""
+
+#: src/paths/instance/templates/qr/QrPage.tsx:131
+#, c-format
+msgid ""
+"Here you can specify a default value for fields that are not fixed. Default "
+"values can be edited by the customer before the payment."
+msgstr ""
+
+#: src/paths/instance/templates/qr/QrPage.tsx:148
+#, c-format
+msgid "Fixed amount"
+msgstr ""
+
+#: src/paths/instance/templates/qr/QrPage.tsx:149
+#, c-format
+msgid "Default amount"
+msgstr ""
+
+#: src/paths/instance/templates/qr/QrPage.tsx:161
+#, c-format
+msgid "Default summary"
+msgstr ""
+
+#: src/paths/instance/templates/qr/QrPage.tsx:177
+#, c-format
+msgid "Print"
+msgstr ""
+
+#: src/paths/instance/templates/qr/QrPage.tsx:184
+#, c-format
+msgid "Setup TOTP"
+msgstr ""
+
+#: src/paths/instance/templates/list/Table.tsx:65
+#, c-format
+msgid "Templates"
+msgstr ""
+
+#: src/paths/instance/templates/list/Table.tsx:70
+#, c-format
+msgid "add new templates"
+msgstr ""
+
+#: src/paths/instance/templates/list/Table.tsx:142
+#, c-format
+msgid "load more templates before the first one"
+msgstr ""
+
+#: src/paths/instance/templates/list/Table.tsx:146
+#, c-format
+msgid "load newer templates"
+msgstr ""
+
+#: src/paths/instance/templates/list/Table.tsx:181
+#, c-format
+msgid "delete selected templates from the database"
+msgstr ""
+
+#: src/paths/instance/templates/list/Table.tsx:188
+#, c-format
+msgid "use template to create new order"
+msgstr ""
+
+#: src/paths/instance/templates/list/Table.tsx:195
+#, c-format
+msgid "create qr code for the template"
+msgstr ""
+
+#: src/paths/instance/templates/list/Table.tsx:210
+#, c-format
+msgid "load more templates after the last one"
+msgstr ""
+
+#: src/paths/instance/templates/list/Table.tsx:214
+#, c-format
+msgid "load older templates"
+msgstr ""
+
+#: src/paths/instance/templates/list/Table.tsx:231
+#, c-format
+msgid "There is no templates yet, add more pressing the + sign"
+msgstr ""
+
+#: src/paths/instance/templates/list/index.tsx:104
+#, c-format
+msgid "template delete successfully"
+msgstr ""
+
+#: src/paths/instance/templates/list/index.tsx:110
+#, c-format
+msgid "could not delete the template"
+msgstr ""
+
+#: src/paths/instance/templates/update/index.tsx:90
+#, c-format
+msgid "could not update template"
+msgstr ""
+
+#: src/paths/instance/webhooks/create/CreatePage.tsx:57
+#, c-format
+msgid "should be one of '%1$s'"
+msgstr ""
+
+#: src/paths/instance/webhooks/create/CreatePage.tsx:85
+#, c-format
+msgid "Webhook ID to use"
+msgstr ""
+
+#: src/paths/instance/webhooks/create/CreatePage.tsx:89
+#, c-format
+msgid "Event"
+msgstr ""
+
+#: src/paths/instance/webhooks/create/CreatePage.tsx:90
+#, c-format
+msgid "The event of the webhook: why the webhook is used"
+msgstr ""
+
+#: src/paths/instance/webhooks/create/CreatePage.tsx:94
+#, c-format
+msgid "Method"
+msgstr ""
+
+#: src/paths/instance/webhooks/create/CreatePage.tsx:95
+#, c-format
+msgid "Method used by the webhook"
+msgstr ""
+
+#: src/paths/instance/webhooks/create/CreatePage.tsx:99
+#, c-format
+msgid "URL"
+msgstr ""
+
+#: src/paths/instance/webhooks/create/CreatePage.tsx:100
+#, c-format
+msgid "URL of the webhook where the customer will be redirected"
+msgstr ""
+
+#: src/paths/instance/webhooks/create/CreatePage.tsx:104
+#, c-format
+msgid "Header"
+msgstr ""
+
+#: src/paths/instance/webhooks/create/CreatePage.tsx:106
+#, c-format
+msgid "Header template of the webhook"
+msgstr ""
+
+#: src/paths/instance/webhooks/create/CreatePage.tsx:111
+#, c-format
+msgid "Body"
+msgstr ""
+
+#: src/paths/instance/webhooks/create/CreatePage.tsx:112
+#, c-format
+msgid "Body template by the webhook"
+msgstr ""
+
+#: src/paths/instance/webhooks/list/Table.tsx:61
+#, c-format
+msgid "Webhooks"
+msgstr ""
+
+#: src/paths/instance/webhooks/list/Table.tsx:66
+#, c-format
+msgid "add new webhooks"
+msgstr ""
+
+#: src/paths/instance/webhooks/list/Table.tsx:137
+#, c-format
+msgid "load more webhooks before the first one"
+msgstr ""
+
+#: src/paths/instance/webhooks/list/Table.tsx:141
+#, c-format
+msgid "load newer webhooks"
+msgstr ""
+
+#: src/paths/instance/webhooks/list/Table.tsx:151
+#, c-format
+msgid "Event type"
+msgstr ""
+
+#: src/paths/instance/webhooks/list/Table.tsx:176
+#, c-format
+msgid "delete selected webhook from the database"
+msgstr ""
+
+#: src/paths/instance/webhooks/list/Table.tsx:198
+#, c-format
+msgid "load more webhooks after the last one"
+msgstr ""
+
+#: src/paths/instance/webhooks/list/Table.tsx:202
+#, c-format
+msgid "load older webhooks"
+msgstr ""
+
+#: src/paths/instance/webhooks/list/Table.tsx:219
+#, c-format
+msgid "There is no webhooks yet, add more pressing the + sign"
+msgstr ""
+
+#: src/paths/instance/webhooks/list/index.tsx:94
+#, c-format
+msgid "webhook delete successfully"
+msgstr ""
+
+#: src/paths/instance/webhooks/list/index.tsx:100
+#, c-format
+msgid "could not delete the webhook"
+msgstr ""
+
+#: src/paths/instance/transfers/create/CreatePage.tsx:63
+#, c-format
+msgid "check the id, does not look valid"
+msgstr ""
+
+#: src/paths/instance/transfers/create/CreatePage.tsx:65
+#, c-format
+msgid "should have 52 characters, current %1$s"
+msgstr ""
+
+#: src/paths/instance/transfers/create/CreatePage.tsx:72
+#, c-format
+msgid "URL doesn't have the right format"
+msgstr ""
+
+#: src/paths/instance/transfers/create/CreatePage.tsx:98
+#, c-format
+msgid "Credited bank account"
+msgstr ""
+
+#: src/paths/instance/transfers/create/CreatePage.tsx:100
+#, c-format
+msgid "Select one account"
+msgstr ""
+
+#: src/paths/instance/transfers/create/CreatePage.tsx:101
+#, c-format
+msgid "Bank account of the merchant where the payment was received"
+msgstr ""
+
+#: src/paths/instance/transfers/create/CreatePage.tsx:105
+#, c-format
+msgid "Wire transfer ID"
+msgstr ""
+
+#: src/paths/instance/transfers/create/CreatePage.tsx:107
+#, c-format
+msgid ""
+"unique identifier of the wire transfer used by the exchange, must be 52 "
+"characters long"
+msgstr ""
+
+#: src/paths/instance/transfers/create/CreatePage.tsx:112
+#, c-format
+msgid ""
+"Base URL of the exchange that made the transfer, should have been in the "
+"wire transfer subject"
+msgstr ""
+
+#: src/paths/instance/transfers/create/CreatePage.tsx:117
+#, c-format
+msgid "Amount credited"
+msgstr ""
+
+#: src/paths/instance/transfers/create/CreatePage.tsx:118
+#, c-format
+msgid "Actual amount that was wired to the merchant's bank account"
+msgstr ""
+
+#: src/paths/instance/transfers/create/index.tsx:58
+#, c-format
+msgid "could not inform transfer"
+msgstr ""
+
+#: src/paths/instance/transfers/list/Table.tsx:61
+#, c-format
+msgid "Transfers"
+msgstr ""
+
+#: src/paths/instance/transfers/list/Table.tsx:66
+#, c-format
+msgid "add new transfer"
+msgstr ""
+
+#: src/paths/instance/transfers/list/Table.tsx:129
+#, c-format
+msgid "load more transfers before the first one"
+msgstr ""
+
+#: src/paths/instance/transfers/list/Table.tsx:133
+#, c-format
+msgid "load newer transfers"
+msgstr ""
+
+#: src/paths/instance/transfers/list/Table.tsx:143
+#, c-format
+msgid "Credit"
+msgstr ""
+
+#: src/paths/instance/transfers/list/Table.tsx:152
+#, c-format
+msgid "Confirmed"
+msgstr ""
+
+#: src/paths/instance/transfers/list/Table.tsx:155
+#, c-format
+msgid "Verified"
+msgstr ""
+
+#: src/paths/instance/transfers/list/Table.tsx:158
+#, c-format
+msgid "Executed at"
+msgstr ""
+
+#: src/paths/instance/transfers/list/Table.tsx:171
+#, c-format
+msgid "yes"
+msgstr ""
+
+#: src/paths/instance/transfers/list/Table.tsx:171
+#, c-format
+msgid "no"
+msgstr ""
+
+#: src/paths/instance/transfers/list/Table.tsx:181
+#, c-format
+msgid "unknown"
+msgstr ""
+
+#: src/paths/instance/transfers/list/Table.tsx:187
+#, c-format
+msgid "delete selected transfer from the database"
+msgstr ""
+
+#: src/paths/instance/transfers/list/Table.tsx:202
+#, c-format
+msgid "load more transfer after the last one"
+msgstr ""
+
+#: src/paths/instance/transfers/list/Table.tsx:206
+#, c-format
+msgid "load older transfers"
+msgstr ""
+
+#: src/paths/instance/transfers/list/Table.tsx:223
+#, c-format
+msgid "There is no transfer yet, add more pressing the + sign"
+msgstr ""
+
+#: src/paths/instance/transfers/list/ListPage.tsx:79
+#, c-format
+msgid "filter by account address"
+msgstr ""
+
+#: src/paths/instance/transfers/list/ListPage.tsx:100
+#, c-format
+msgid "only show wire transfers confirmed by the merchant"
+msgstr ""
+
+#: src/paths/instance/transfers/list/ListPage.tsx:110
+#, c-format
+msgid "only show wire transfers claimed by the exchange"
+msgstr ""
+
+#: src/paths/instance/transfers/list/ListPage.tsx:113
+#, c-format
+msgid "Unverified"
+msgstr ""
+
+#: src/paths/admin/create/CreatePage.tsx:69
+#, c-format
+msgid "is not valid"
+msgstr ""
+
+#: src/paths/admin/create/CreatePage.tsx:94
+#, c-format
+msgid "is not a number"
+msgstr ""
+
+#: src/paths/admin/create/CreatePage.tsx:96
+#, c-format
+msgid "must be 1 or greater"
+msgstr ""
+
+#: src/paths/admin/create/CreatePage.tsx:107
+#, c-format
+msgid "max 7 lines"
+msgstr ""
+
+#: src/paths/admin/create/CreatePage.tsx:178
+#, c-format
+msgid "change authorization configuration"
+msgstr ""
+
+#: src/paths/admin/create/CreatePage.tsx:217
+#, c-format
+msgid "Need to complete marked fields and choose authorization method"
+msgstr ""
+
+#: src/components/form/InputPaytoForm.tsx:82
+#, c-format
+msgid "This is not a valid bitcoin address."
+msgstr ""
+
+#: src/components/form/InputPaytoForm.tsx:95
+#, c-format
+msgid "This is not a valid Ethereum address."
+msgstr ""
+
+#: src/components/form/InputPaytoForm.tsx:118
+#, c-format
+msgid "IBAN numbers usually have more that 4 digits"
+msgstr ""
+
+#: src/components/form/InputPaytoForm.tsx:120
+#, c-format
+msgid "IBAN numbers usually have less that 34 digits"
+msgstr ""
+
+#: src/components/form/InputPaytoForm.tsx:128
+#, c-format
+msgid "IBAN country code not found"
+msgstr ""
+
+#: src/components/form/InputPaytoForm.tsx:153
+#, c-format
+msgid "IBAN number is not valid, checksum is wrong"
+msgstr ""
+
+#: src/components/form/InputPaytoForm.tsx:248
+#, c-format
+msgid "Target type"
+msgstr ""
+
+#: src/components/form/InputPaytoForm.tsx:249
+#, c-format
+msgid "Method to use for wire transfer"
+msgstr ""
+
+#: src/components/form/InputPaytoForm.tsx:258
+#, c-format
+msgid "Routing"
+msgstr ""
+
+#: src/components/form/InputPaytoForm.tsx:259
+#, c-format
+msgid "Routing number."
+msgstr ""
+
+#: src/components/form/InputPaytoForm.tsx:263
+#, c-format
+msgid "Account"
+msgstr ""
+
+#: src/components/form/InputPaytoForm.tsx:264
+#, c-format
+msgid "Account number."
+msgstr ""
+
+#: src/components/form/InputPaytoForm.tsx:273
+#, c-format
+msgid "Business Identifier Code."
+msgstr ""
+
+#: src/components/form/InputPaytoForm.tsx:282
+#, c-format
+msgid "Bank Account Number."
+msgstr ""
+
+#: src/components/form/InputPaytoForm.tsx:292
+#, c-format
+msgid "Unified Payment Interface."
+msgstr ""
+
+#: src/components/form/InputPaytoForm.tsx:301
+#, c-format
+msgid "Bitcoin protocol."
+msgstr ""
+
+#: src/components/form/InputPaytoForm.tsx:310
+#, c-format
+msgid "Ethereum protocol."
+msgstr ""
+
+#: src/components/form/InputPaytoForm.tsx:319
+#, c-format
+msgid "Interledger protocol."
+msgstr ""
+
+#: src/components/form/InputPaytoForm.tsx:328
+#, c-format
+msgid "Host"
+msgstr ""
+
+#: src/components/form/InputPaytoForm.tsx:329
+#, c-format
+msgid "Bank host."
+msgstr ""
+
+#: src/components/form/InputPaytoForm.tsx:334
+#, c-format
+msgid "Bank account."
+msgstr ""
+
+#: src/components/form/InputPaytoForm.tsx:343
+#, c-format
+msgid "Bank account owner's name."
+msgstr ""
+
+#: src/components/form/InputPaytoForm.tsx:370
+#, c-format
+msgid "No accounts yet."
+msgstr ""
+
+#: src/components/instance/DefaultInstanceFormFields.tsx:52
+#, c-format
+msgid ""
+"Name of the instance in URLs. The 'default' instance is special in that it "
+"is used to administer other instances."
+msgstr ""
+
+#: src/components/instance/DefaultInstanceFormFields.tsx:58
+#, c-format
+msgid "Business name"
+msgstr ""
+
+#: src/components/instance/DefaultInstanceFormFields.tsx:59
+#, c-format
+msgid "Legal name of the business represented by this instance."
+msgstr ""
+
+#: src/components/instance/DefaultInstanceFormFields.tsx:64
+#, c-format
+msgid "Email"
+msgstr ""
+
+#: src/components/instance/DefaultInstanceFormFields.tsx:65
+#, c-format
+msgid "Contact email"
+msgstr ""
+
+#: src/components/instance/DefaultInstanceFormFields.tsx:70
+#, c-format
+msgid "Website URL"
+msgstr ""
+
+#: src/components/instance/DefaultInstanceFormFields.tsx:71
+#, c-format
+msgid "URL."
+msgstr ""
+
+#: src/components/instance/DefaultInstanceFormFields.tsx:76
+#, c-format
+msgid "Logo"
+msgstr ""
+
+#: src/components/instance/DefaultInstanceFormFields.tsx:77
+#, c-format
+msgid "Logo image."
+msgstr ""
+
+#: src/components/instance/DefaultInstanceFormFields.tsx:82
+#, c-format
+msgid "Bank account"
+msgstr ""
+
+#: src/components/instance/DefaultInstanceFormFields.tsx:83
+#, c-format
+msgid "URI specifying bank account for crediting revenue."
+msgstr ""
+
+#: src/components/instance/DefaultInstanceFormFields.tsx:88
+#, c-format
+msgid "Default max deposit fee"
+msgstr ""
+
+#: src/components/instance/DefaultInstanceFormFields.tsx:89
+#, c-format
+msgid ""
+"Maximum deposit fees this merchant is willing to pay per order by default."
+msgstr ""
+
+#: src/components/instance/DefaultInstanceFormFields.tsx:94
+#, c-format
+msgid "Default max wire fee"
+msgstr ""
+
+#: src/components/instance/DefaultInstanceFormFields.tsx:95
+#, c-format
+msgid ""
+"Maximum wire fees this merchant is willing to pay per wire transfer by "
+"default."
+msgstr ""
+
+#: src/components/instance/DefaultInstanceFormFields.tsx:100
+#, c-format
+msgid "Default wire fee amortization"
+msgstr ""
+
+#: src/components/instance/DefaultInstanceFormFields.tsx:101
+#, c-format
+msgid ""
+"Number of orders excess wire transfer fees will be divided by to compute per "
+"order surcharge."
+msgstr ""
+
+#: src/components/instance/DefaultInstanceFormFields.tsx:107
+#, c-format
+msgid "Physical location of the merchant."
+msgstr ""
+
+#: src/components/instance/DefaultInstanceFormFields.tsx:114
+#, c-format
+msgid "Jurisdiction"
+msgstr ""
+
+#: src/components/instance/DefaultInstanceFormFields.tsx:115
+#, c-format
+msgid "Jurisdiction for legal disputes with the merchant."
+msgstr ""
+
+#: src/components/instance/DefaultInstanceFormFields.tsx:122
+#, c-format
+msgid "Default payment delay"
+msgstr ""
+
+#: src/components/instance/DefaultInstanceFormFields.tsx:124
+#, c-format
+msgid ""
+"Time customers have to pay an order before the offer expires by default."
+msgstr ""
+
+#: src/components/instance/DefaultInstanceFormFields.tsx:129
+#, c-format
+msgid "Default wire transfer delay"
+msgstr ""
+
+#: src/components/instance/DefaultInstanceFormFields.tsx:130
+#, c-format
+msgid ""
+"Maximum time an exchange is allowed to delay wiring funds to the merchant, "
+"enabling it to aggregate smaller payments into larger wire transfers and "
+"reducing wire fees."
+msgstr ""
+
+#: src/paths/instance/update/UpdatePage.tsx:164
+#, c-format
+msgid "Instance id"
+msgstr ""
+
+#: src/paths/instance/update/UpdatePage.tsx:173
+#, c-format
+msgid "Change the authorization method use for this instance."
+msgstr ""
+
+#: src/paths/instance/update/UpdatePage.tsx:182
+#, c-format
+msgid "Manage access token"
+msgstr ""
+
+#: src/paths/instance/update/index.tsx:112
+#, c-format
+msgid "Failed to create instance"
+msgstr ""
+
+#: src/components/exception/login.tsx:74
+#, c-format
+msgid "Login required"
+msgstr ""
+
+#: src/components/exception/login.tsx:80
+#, c-format
+msgid "Please enter your access token."
+msgstr ""
+
+#: src/components/exception/login.tsx:108
+#, c-format
+msgid "Access Token"
+msgstr ""
+
+#: src/InstanceRoutes.tsx:171
+#, c-format
+msgid "The request to the backend take too long and was cancelled"
+msgstr ""
+
+#: src/InstanceRoutes.tsx:172
+#, c-format
+msgid "Diagnostic from %1$s is \"%2$s\""
+msgstr ""
+
+#: src/InstanceRoutes.tsx:178
+#, c-format
+msgid "The backend reported a problem: HTTP status #%1$s"
+msgstr ""
+
+#: src/InstanceRoutes.tsx:179
+#, c-format
+msgid "Diagnostic from %1$s is '%2$s'"
+msgstr ""
+
+#: src/InstanceRoutes.tsx:196
+#, c-format
+msgid "Access denied"
+msgstr ""
+
+#: src/InstanceRoutes.tsx:197
+#, c-format
+msgid "The access token provided is invalid."
+msgstr ""
+
+#: src/InstanceRoutes.tsx:212
+#, c-format
+msgid "No 'default' instance configured yet."
+msgstr ""
+
+#: src/InstanceRoutes.tsx:213
+#, c-format
+msgid "Create a 'default' instance to begin using the merchant backoffice."
+msgstr ""
+
+#: src/InstanceRoutes.tsx:630
+#, c-format
+msgid "The access token provided is invalid"
+msgstr ""
+
+#: src/InstanceRoutes.tsx:664
+#, c-format
+msgid "Hide for today"
+msgstr ""
+
+#: src/components/menu/SideBar.tsx:82
+#, c-format
+msgid "Instance"
+msgstr ""
+
+#: src/components/menu/SideBar.tsx:91
+#, c-format
+msgid "Settings"
+msgstr ""
+
+#: src/components/menu/SideBar.tsx:167
+#, c-format
+msgid "Connection"
+msgstr ""
+
+#: src/components/menu/SideBar.tsx:209
+#, c-format
+msgid "New"
+msgstr ""
+
+#: src/components/menu/SideBar.tsx:219
+#, c-format
+msgid "List"
+msgstr ""
+
+#: src/components/menu/SideBar.tsx:234
+#, c-format
+msgid "Log out"
+msgstr ""
+
+#: src/ApplicationReadyRoutes.tsx:71
+#, c-format
+msgid "Check your token is valid"
+msgstr ""
+
+#: src/ApplicationReadyRoutes.tsx:90
+#, c-format
+msgid "Couldn't access the server."
+msgstr ""
+
+#: src/ApplicationReadyRoutes.tsx:91
+#, c-format
+msgid "Could not infer instance id from url %1$s"
+msgstr ""
+
+#: src/Application.tsx:104
+#, c-format
+msgid "Server not found"
+msgstr ""
+
+#: src/Application.tsx:118
+#, c-format
+msgid "Server response with an error code"
+msgstr ""
+
+#: src/Application.tsx:120
+#, c-format
+msgid "Got message %1$s from %2$s"
+msgstr ""
+
+#: src/Application.tsx:131
+#, c-format
+msgid "Response from server is unreadable, http status: %1$s"
+msgstr ""
+
+#: src/Application.tsx:144
+#, c-format
+msgid "Unexpected Error"
+msgstr ""
+
+#: src/components/form/InputArray.tsx:101
+#, c-format
+msgid "The value %1$s is invalid for a payment url"
+msgstr ""
+
+#: src/components/form/InputArray.tsx:110
+#, c-format
+msgid "add element to the list"
+msgstr ""
+
+#: src/components/form/InputArray.tsx:112
+#, c-format
+msgid "add"
+msgstr ""
+
+#: src/components/form/InputSecured.tsx:37
+#, c-format
+msgid "Deleting"
+msgstr ""
+
+#: src/components/form/InputSecured.tsx:41
+#, c-format
+msgid "Changing"
+msgstr ""
+
+#: src/paths/instance/orders/create/OrderCreatedSuccessfully.tsx:87
+#, c-format
+msgid "Order ID"
+msgstr ""
+
+#: src/paths/instance/orders/create/OrderCreatedSuccessfully.tsx:101
+#, c-format
+msgid "Payment URL"
+msgstr ""
diff --git a/packages/auditor-backoffice-ui/src/i18n/en.po 
b/packages/auditor-backoffice-ui/src/i18n/en.po
new file mode 100644
index 000000000..d8d0bae29
--- /dev/null
+++ b/packages/auditor-backoffice-ui/src/i18n/en.po
@@ -0,0 +1,2741 @@
+# This file is part of TALER
+# (C) 2016 GNUnet e.V.
+#
+# TALER is free software; you can redistribute it and/or modify it under the
+# terms of the GNU General Public License as published by the Free Software
+# Foundation; either version 3, or (at your option) any later version.
+#
+# TALER is distributed in the hope that it will be useful, but WITHOUT ANY
+# WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
+# A PARTICULAR PURPOSE.  See the GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License along with
+# TALER; see the file COPYING.  If not, see <http://www.gnu.org/licenses/>
+#
+#, fuzzy
+msgid ""
+msgstr ""
+"Project-Id-Version: Taler Wallet\n"
+"Report-Msgid-Bugs-To: taler@gnu.org\n"
+"POT-Creation-Date: 2016-11-23 00:00+0100\n"
+"PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n"
+"Last-Translator: FULL NAME <EMAIL@ADDRESS>\n"
+"Language-Team: LANGUAGE <LL@li.org>\n"
+"Language: \n"
+"MIME-Version: 1.0\n"
+"Content-Type: text/plain; charset=UTF-8\n"
+"Content-Transfer-Encoding: 8bit\n"
+"Plural-Forms: nplurals=2; plural=(n != 1);\n"
+
+#: src/components/modal/index.tsx:71
+#, c-format
+msgid "Cancel"
+msgstr ""
+
+#: src/components/modal/index.tsx:79
+#, c-format
+msgid "%1$s"
+msgstr ""
+
+#: src/components/modal/index.tsx:84
+#, c-format
+msgid "Close"
+msgstr ""
+
+#: src/components/modal/index.tsx:124
+#, c-format
+msgid "Continue"
+msgstr ""
+
+#: src/components/modal/index.tsx:178
+#, c-format
+msgid "Clear"
+msgstr ""
+
+#: src/components/modal/index.tsx:190
+#, c-format
+msgid "Confirm"
+msgstr ""
+
+#: src/components/modal/index.tsx:296
+#, c-format
+msgid "is not the same as the current access token"
+msgstr ""
+
+#: src/components/modal/index.tsx:299
+#, c-format
+msgid "cannot be empty"
+msgstr ""
+
+#: src/components/modal/index.tsx:301
+#, c-format
+msgid "cannot be the same as the old token"
+msgstr ""
+
+#: src/components/modal/index.tsx:305
+#, c-format
+msgid "is not the same"
+msgstr ""
+
+#: src/components/modal/index.tsx:315
+#, c-format
+msgid "You are updating the access token from instance with id %1$s"
+msgstr ""
+
+#: src/components/modal/index.tsx:331
+#, c-format
+msgid "Old access token"
+msgstr ""
+
+#: src/components/modal/index.tsx:332
+#, c-format
+msgid "access token currently in use"
+msgstr ""
+
+#: src/components/modal/index.tsx:338
+#, c-format
+msgid "New access token"
+msgstr ""
+
+#: src/components/modal/index.tsx:339
+#, c-format
+msgid "next access token to be used"
+msgstr ""
+
+#: src/components/modal/index.tsx:344
+#, c-format
+msgid "Repeat access token"
+msgstr ""
+
+#: src/components/modal/index.tsx:345
+#, c-format
+msgid "confirm the same access token"
+msgstr ""
+
+#: src/components/modal/index.tsx:350
+#, c-format
+msgid "Clearing the access token will mean public access to the instance"
+msgstr ""
+
+#: src/components/modal/index.tsx:377
+#, c-format
+msgid "cannot be the same as the old access token"
+msgstr ""
+
+#: src/components/modal/index.tsx:394
+#, c-format
+msgid "You are setting the access token for the new instance"
+msgstr ""
+
+#: src/components/modal/index.tsx:420
+#, c-format
+msgid ""
+"With external authorization method no check will be done by the merchant "
+"backend"
+msgstr ""
+
+#: src/components/modal/index.tsx:436
+#, c-format
+msgid "Set external authorization"
+msgstr ""
+
+#: src/components/modal/index.tsx:448
+#, c-format
+msgid "Set access token"
+msgstr ""
+
+#: src/components/modal/index.tsx:470
+#, c-format
+msgid "Operation in progress..."
+msgstr ""
+
+#: src/components/modal/index.tsx:479
+#, c-format
+msgid "The operation will be automatically canceled after %1$s seconds"
+msgstr ""
+
+#: src/paths/admin/list/TableActive.tsx:80
+#, c-format
+msgid "Instances"
+msgstr ""
+
+#: src/paths/admin/list/TableActive.tsx:93
+#, c-format
+msgid "Delete"
+msgstr ""
+
+#: src/paths/admin/list/TableActive.tsx:99
+#, c-format
+msgid "add new instance"
+msgstr ""
+
+#: src/paths/admin/list/TableActive.tsx:178
+#, c-format
+msgid "ID"
+msgstr ""
+
+#: src/paths/admin/list/TableActive.tsx:181
+#, c-format
+msgid "Name"
+msgstr ""
+
+#: src/paths/admin/list/TableActive.tsx:220
+#, c-format
+msgid "Edit"
+msgstr ""
+
+#: src/paths/admin/list/TableActive.tsx:237
+#, c-format
+msgid "Purge"
+msgstr ""
+
+#: src/paths/admin/list/TableActive.tsx:261
+#, c-format
+msgid "There is no instances yet, add more pressing the + sign"
+msgstr ""
+
+#: src/paths/admin/list/View.tsx:68
+#, c-format
+msgid "Only show active instances"
+msgstr ""
+
+#: src/paths/admin/list/View.tsx:71
+#, c-format
+msgid "Active"
+msgstr ""
+
+#: src/paths/admin/list/View.tsx:78
+#, c-format
+msgid "Only show deleted instances"
+msgstr ""
+
+#: src/paths/admin/list/View.tsx:81
+#, c-format
+msgid "Deleted"
+msgstr ""
+
+#: src/paths/admin/list/View.tsx:88
+#, c-format
+msgid "Show all instances"
+msgstr ""
+
+#: src/paths/admin/list/View.tsx:91
+#, c-format
+msgid "All"
+msgstr ""
+
+#: src/paths/admin/list/index.tsx:101
+#, c-format
+msgid "Instance \"%1$s\" (ID: %2$s) has been deleted"
+msgstr ""
+
+#: src/paths/admin/list/index.tsx:106
+#, c-format
+msgid "Failed to delete instance"
+msgstr ""
+
+#: src/paths/admin/list/index.tsx:124
+#, c-format
+msgid "Instance '%1$s' (ID: %2$s) has been disabled"
+msgstr ""
+
+#: src/paths/admin/list/index.tsx:129
+#, c-format
+msgid "Failed to purge instance"
+msgstr ""
+
+#: src/paths/instance/kyc/list/ListPage.tsx:41
+#, c-format
+msgid "Pending KYC verification"
+msgstr ""
+
+#: src/paths/instance/kyc/list/ListPage.tsx:66
+#, c-format
+msgid "Timed out"
+msgstr ""
+
+#: src/paths/instance/kyc/list/ListPage.tsx:103
+#, c-format
+msgid "Exchange"
+msgstr ""
+
+#: src/paths/instance/kyc/list/ListPage.tsx:106
+#, c-format
+msgid "Target account"
+msgstr ""
+
+#: src/paths/instance/kyc/list/ListPage.tsx:109
+#, c-format
+msgid "KYC URL"
+msgstr ""
+
+#: src/paths/instance/kyc/list/ListPage.tsx:144
+#, c-format
+msgid "Code"
+msgstr ""
+
+#: src/paths/instance/kyc/list/ListPage.tsx:147
+#, c-format
+msgid "Http Status"
+msgstr ""
+
+#: src/paths/instance/kyc/list/ListPage.tsx:177
+#, c-format
+msgid "No pending kyc verification!"
+msgstr ""
+
+#: src/components/form/InputDate.tsx:123
+#, c-format
+msgid "change value to unknown date"
+msgstr ""
+
+#: src/components/form/InputDate.tsx:124
+#, c-format
+msgid "change value to empty"
+msgstr ""
+
+#: src/components/form/InputDate.tsx:131
+#, c-format
+msgid "clear"
+msgstr ""
+
+#: src/components/form/InputDate.tsx:136
+#, c-format
+msgid "change value to never"
+msgstr ""
+
+#: src/components/form/InputDate.tsx:141
+#, c-format
+msgid "never"
+msgstr ""
+
+#: src/components/form/InputLocation.tsx:29
+#, c-format
+msgid "Country"
+msgstr ""
+
+#: src/components/form/InputLocation.tsx:33
+#, c-format
+msgid "Address"
+msgstr ""
+
+#: src/components/form/InputLocation.tsx:39
+#, c-format
+msgid "Building number"
+msgstr ""
+
+#: src/components/form/InputLocation.tsx:41
+#, c-format
+msgid "Building name"
+msgstr ""
+
+#: src/components/form/InputLocation.tsx:42
+#, c-format
+msgid "Street"
+msgstr ""
+
+#: src/components/form/InputLocation.tsx:43
+#, c-format
+msgid "Post code"
+msgstr ""
+
+#: src/components/form/InputLocation.tsx:44
+#, c-format
+msgid "Town location"
+msgstr ""
+
+#: src/components/form/InputLocation.tsx:45
+#, c-format
+msgid "Town"
+msgstr ""
+
+#: src/components/form/InputLocation.tsx:46
+#, c-format
+msgid "District"
+msgstr ""
+
+#: src/components/form/InputLocation.tsx:49
+#, c-format
+msgid "Country subdivision"
+msgstr ""
+
+#: src/components/form/InputSearchProduct.tsx:66
+#, c-format
+msgid "Product id"
+msgstr ""
+
+#: src/components/form/InputSearchProduct.tsx:69
+#, c-format
+msgid "Description"
+msgstr ""
+
+#: src/components/form/InputSearchProduct.tsx:94
+#, c-format
+msgid "Product"
+msgstr ""
+
+#: src/components/form/InputSearchProduct.tsx:95
+#, c-format
+msgid "search products by it's description or id"
+msgstr ""
+
+#: src/components/form/InputSearchProduct.tsx:151
+#, c-format
+msgid "no products found with that description"
+msgstr ""
+
+#: src/components/product/InventoryProductForm.tsx:56
+#, c-format
+msgid "You must enter a valid product identifier."
+msgstr ""
+
+#: src/components/product/InventoryProductForm.tsx:64
+#, c-format
+msgid "Quantity must be greater than 0!"
+msgstr ""
+
+#: src/components/product/InventoryProductForm.tsx:76
+#, c-format
+msgid ""
+"This quantity exceeds remaining stock. Currently, only %1$s units remain "
+"unreserved in stock."
+msgstr ""
+
+#: src/components/product/InventoryProductForm.tsx:109
+#, c-format
+msgid "Quantity"
+msgstr ""
+
+#: src/components/product/InventoryProductForm.tsx:110
+#, c-format
+msgid "how many products will be added"
+msgstr ""
+
+#: src/components/product/InventoryProductForm.tsx:117
+#, c-format
+msgid "Add from inventory"
+msgstr ""
+
+#: src/components/form/InputImage.tsx:105
+#, c-format
+msgid "Image should be smaller than 1 MB"
+msgstr ""
+
+#: src/components/form/InputImage.tsx:110
+#, c-format
+msgid "Add"
+msgstr ""
+
+#: src/components/form/InputImage.tsx:115
+#, c-format
+msgid "Remove"
+msgstr ""
+
+#: src/components/form/InputTaxes.tsx:113
+#, c-format
+msgid "No taxes configured for this product."
+msgstr ""
+
+#: src/components/form/InputTaxes.tsx:119
+#, c-format
+msgid "Amount"
+msgstr ""
+
+#: src/components/form/InputTaxes.tsx:120
+#, c-format
+msgid ""
+"Taxes can be in currencies that differ from the main currency used by the "
+"merchant."
+msgstr ""
+
+#: src/components/form/InputTaxes.tsx:122
+#, c-format
+msgid ""
+"Enter currency and value separated with a colon, e.g. &quot;USD:2.3&quot;."
+msgstr ""
+
+#: src/components/form/InputTaxes.tsx:131
+#, c-format
+msgid "Legal name of the tax, e.g. VAT or import duties."
+msgstr ""
+
+#: src/components/form/InputTaxes.tsx:137
+#, c-format
+msgid "add tax to the tax list"
+msgstr ""
+
+#: src/components/product/NonInventoryProductForm.tsx:72
+#, c-format
+msgid "describe and add a product that is not in the inventory list"
+msgstr ""
+
+#: src/components/product/NonInventoryProductForm.tsx:75
+#, c-format
+msgid "Add custom product"
+msgstr ""
+
+#: src/components/product/NonInventoryProductForm.tsx:86
+#, c-format
+msgid "Complete information of the product"
+msgstr ""
+
+#: src/components/product/NonInventoryProductForm.tsx:185
+#, c-format
+msgid "Image"
+msgstr ""
+
+#: src/components/product/NonInventoryProductForm.tsx:186
+#, c-format
+msgid "photo of the product"
+msgstr ""
+
+#: src/components/product/NonInventoryProductForm.tsx:192
+#, c-format
+msgid "full product description"
+msgstr ""
+
+#: src/components/product/NonInventoryProductForm.tsx:196
+#, c-format
+msgid "Unit"
+msgstr ""
+
+#: src/components/product/NonInventoryProductForm.tsx:197
+#, c-format
+msgid "name of the product unit"
+msgstr ""
+
+#: src/components/product/NonInventoryProductForm.tsx:201
+#, c-format
+msgid "Price"
+msgstr ""
+
+#: src/components/product/NonInventoryProductForm.tsx:202
+#, c-format
+msgid "amount in the current currency"
+msgstr ""
+
+#: src/components/product/NonInventoryProductForm.tsx:211
+#, c-format
+msgid "Taxes"
+msgstr ""
+
+#: src/components/product/ProductList.tsx:38
+#, c-format
+msgid "image"
+msgstr ""
+
+#: src/components/product/ProductList.tsx:41
+#, c-format
+msgid "description"
+msgstr ""
+
+#: src/components/product/ProductList.tsx:44
+#, c-format
+msgid "quantity"
+msgstr ""
+
+#: src/components/product/ProductList.tsx:47
+#, c-format
+msgid "unit price"
+msgstr ""
+
+#: src/components/product/ProductList.tsx:50
+#, c-format
+msgid "total price"
+msgstr ""
+
+#: src/paths/instance/orders/create/CreatePage.tsx:153
+#, c-format
+msgid "required"
+msgstr ""
+
+#: src/paths/instance/orders/create/CreatePage.tsx:157
+#, c-format
+msgid "not valid"
+msgstr ""
+
+#: src/paths/instance/orders/create/CreatePage.tsx:159
+#, c-format
+msgid "must be greater than 0"
+msgstr ""
+
+#: src/paths/instance/orders/create/CreatePage.tsx:164
+#, c-format
+msgid "not a valid json"
+msgstr ""
+
+#: src/paths/instance/orders/create/CreatePage.tsx:170
+#, c-format
+msgid "should be in the future"
+msgstr ""
+
+#: src/paths/instance/orders/create/CreatePage.tsx:173
+#, c-format
+msgid "refund deadline cannot be before pay deadline"
+msgstr ""
+
+#: src/paths/instance/orders/create/CreatePage.tsx:179
+#, c-format
+msgid "wire transfer deadline cannot be before refund deadline"
+msgstr ""
+
+#: src/paths/instance/orders/create/CreatePage.tsx:190
+#, c-format
+msgid "wire transfer deadline cannot be before pay deadline"
+msgstr ""
+
+#: src/paths/instance/orders/create/CreatePage.tsx:197
+#, c-format
+msgid "should have a refund deadline"
+msgstr ""
+
+#: src/paths/instance/orders/create/CreatePage.tsx:202
+#, c-format
+msgid "auto refund cannot be after refund deadline"
+msgstr ""
+
+#: src/paths/instance/orders/create/CreatePage.tsx:360
+#, c-format
+msgid "Manage products in order"
+msgstr ""
+
+#: src/paths/instance/orders/create/CreatePage.tsx:369
+#, c-format
+msgid "Manage list of products in the order."
+msgstr ""
+
+#: src/paths/instance/orders/create/CreatePage.tsx:391
+#, c-format
+msgid "Remove this product from the order."
+msgstr ""
+
+#: src/paths/instance/orders/create/CreatePage.tsx:415
+#, c-format
+msgid "Total price"
+msgstr ""
+
+#: src/paths/instance/orders/create/CreatePage.tsx:417
+#, c-format
+msgid "total product price added up"
+msgstr ""
+
+#: src/paths/instance/orders/create/CreatePage.tsx:430
+#, c-format
+msgid "Amount to be paid by the customer"
+msgstr ""
+
+#: src/paths/instance/orders/create/CreatePage.tsx:436
+#, c-format
+msgid "Order price"
+msgstr ""
+
+#: src/paths/instance/orders/create/CreatePage.tsx:437
+#, c-format
+msgid "final order price"
+msgstr ""
+
+#: src/paths/instance/orders/create/CreatePage.tsx:444
+#, c-format
+msgid "Summary"
+msgstr ""
+
+#: src/paths/instance/orders/create/CreatePage.tsx:445
+#, c-format
+msgid "Title of the order to be shown to the customer"
+msgstr ""
+
+#: src/paths/instance/orders/create/CreatePage.tsx:450
+#, c-format
+msgid "Shipping and Fulfillment"
+msgstr ""
+
+#: src/paths/instance/orders/create/CreatePage.tsx:455
+#, c-format
+msgid "Delivery date"
+msgstr ""
+
+#: src/paths/instance/orders/create/CreatePage.tsx:456
+#, c-format
+msgid "Deadline for physical delivery assured by the merchant."
+msgstr ""
+
+#: src/paths/instance/orders/create/CreatePage.tsx:461
+#, c-format
+msgid "Location"
+msgstr ""
+
+#: src/paths/instance/orders/create/CreatePage.tsx:462
+#, c-format
+msgid "address where the products will be delivered"
+msgstr ""
+
+#: src/paths/instance/orders/create/CreatePage.tsx:469
+#, c-format
+msgid "Fulfillment URL"
+msgstr ""
+
+#: src/paths/instance/orders/create/CreatePage.tsx:470
+#, c-format
+msgid "URL to which the user will be redirected after successful payment."
+msgstr ""
+
+#: src/paths/instance/orders/create/CreatePage.tsx:476
+#, c-format
+msgid "Taler payment options"
+msgstr ""
+
+#: src/paths/instance/orders/create/CreatePage.tsx:477
+#, c-format
+msgid "Override default Taler payment settings for this order"
+msgstr ""
+
+#: src/paths/instance/orders/create/CreatePage.tsx:481
+#, c-format
+msgid "Payment deadline"
+msgstr ""
+
+#: src/paths/instance/orders/create/CreatePage.tsx:482
+#, c-format
+msgid ""
+"Deadline for the customer to pay for the offer before it expires. Inventory "
+"products will be reserved until this deadline."
+msgstr ""
+
+#: src/paths/instance/orders/create/CreatePage.tsx:486
+#, c-format
+msgid "Refund deadline"
+msgstr ""
+
+#: src/paths/instance/orders/create/CreatePage.tsx:487
+#, c-format
+msgid "Time until which the order can be refunded by the merchant."
+msgstr ""
+
+#: src/paths/instance/orders/create/CreatePage.tsx:491
+#, c-format
+msgid "Wire transfer deadline"
+msgstr ""
+
+#: src/paths/instance/orders/create/CreatePage.tsx:492
+#, c-format
+msgid "Deadline for the exchange to make the wire transfer."
+msgstr ""
+
+#: src/paths/instance/orders/create/CreatePage.tsx:496
+#, c-format
+msgid "Auto-refund deadline"
+msgstr ""
+
+#: src/paths/instance/orders/create/CreatePage.tsx:497
+#, c-format
+msgid ""
+"Time until which the wallet will automatically check for refunds without "
+"user interaction."
+msgstr ""
+
+#: src/paths/instance/orders/create/CreatePage.tsx:502
+#, c-format
+msgid "Maximum deposit fee"
+msgstr ""
+
+#: src/paths/instance/orders/create/CreatePage.tsx:503
+#, c-format
+msgid ""
+"Maximum deposit fees the merchant is willing to cover for this order. Higher "
+"deposit fees must be covered in full by the consumer."
+msgstr ""
+
+#: src/paths/instance/orders/create/CreatePage.tsx:507
+#, c-format
+msgid "Maximum wire fee"
+msgstr ""
+
+#: src/paths/instance/orders/create/CreatePage.tsx:508
+#, c-format
+msgid ""
+"Maximum aggregate wire fees the merchant is willing to cover for this order. "
+"Wire fees exceeding this amount are to be covered by the customers."
+msgstr ""
+
+#: src/paths/instance/orders/create/CreatePage.tsx:512
+#, c-format
+msgid "Wire fee amortization"
+msgstr ""
+
+#: src/paths/instance/orders/create/CreatePage.tsx:513
+#, c-format
+msgid ""
+"Factor by which wire fees exceeding the above threshold are divided to "
+"determine the share of excess wire fees to be paid explicitly by the "
+"consumer."
+msgstr ""
+
+#: src/paths/instance/orders/create/CreatePage.tsx:517
+#, c-format
+msgid "Create token"
+msgstr ""
+
+#: src/paths/instance/orders/create/CreatePage.tsx:518
+#, c-format
+msgid ""
+"Uncheck this option if the merchant backend generated an order ID with "
+"enough entropy to prevent adversarial claims."
+msgstr ""
+
+#: src/paths/instance/orders/create/CreatePage.tsx:522
+#, c-format
+msgid "Minimum age required"
+msgstr ""
+
+#: src/paths/instance/orders/create/CreatePage.tsx:523
+#, c-format
+msgid ""
+"Any value greater than 0 will limit the coins able be used to pay this "
+"contract. If empty the age restriction will be defined by the products"
+msgstr ""
+
+#: src/paths/instance/orders/create/CreatePage.tsx:526
+#, c-format
+msgid "Min age defined by the producs is %1$s"
+msgstr ""
+
+#: src/paths/instance/orders/create/CreatePage.tsx:534
+#, c-format
+msgid "Additional information"
+msgstr ""
+
+#: src/paths/instance/orders/create/CreatePage.tsx:535
+#, c-format
+msgid "Custom information to be included in the contract for this order."
+msgstr ""
+
+#: src/paths/instance/orders/create/CreatePage.tsx:541
+#, c-format
+msgid "You must enter a value in JavaScript Object Notation (JSON)."
+msgstr ""
+
+#: src/components/picker/DurationPicker.tsx:55
+#, c-format
+msgid "days"
+msgstr ""
+
+#: src/components/picker/DurationPicker.tsx:65
+#, c-format
+msgid "hours"
+msgstr ""
+
+#: src/components/picker/DurationPicker.tsx:76
+#, c-format
+msgid "minutes"
+msgstr ""
+
+#: src/components/picker/DurationPicker.tsx:87
+#, c-format
+msgid "seconds"
+msgstr ""
+
+#: src/components/form/InputDuration.tsx:53
+#, c-format
+msgid "forever"
+msgstr ""
+
+#: src/components/form/InputDuration.tsx:62
+#, c-format
+msgid "%1$sM"
+msgstr ""
+
+#: src/components/form/InputDuration.tsx:64
+#, c-format
+msgid "%1$sY"
+msgstr ""
+
+#: src/components/form/InputDuration.tsx:66
+#, c-format
+msgid "%1$sd"
+msgstr ""
+
+#: src/components/form/InputDuration.tsx:68
+#, c-format
+msgid "%1$sh"
+msgstr ""
+
+#: src/components/form/InputDuration.tsx:70
+#, c-format
+msgid "%1$smin"
+msgstr ""
+
+#: src/components/form/InputDuration.tsx:72
+#, c-format
+msgid "%1$ssec"
+msgstr ""
+
+#: src/paths/instance/orders/list/Table.tsx:75
+#, c-format
+msgid "Orders"
+msgstr ""
+
+#: src/paths/instance/orders/list/Table.tsx:81
+#, c-format
+msgid "create order"
+msgstr ""
+
+#: src/paths/instance/orders/list/Table.tsx:147
+#, c-format
+msgid "load newer orders"
+msgstr ""
+
+#: src/paths/instance/orders/list/Table.tsx:154
+#, c-format
+msgid "Date"
+msgstr ""
+
+#: src/paths/instance/orders/list/Table.tsx:200
+#, c-format
+msgid "Refund"
+msgstr ""
+
+#: src/paths/instance/orders/list/Table.tsx:209
+#, c-format
+msgid "copy url"
+msgstr ""
+
+#: src/paths/instance/orders/list/Table.tsx:225
+#, c-format
+msgid "load older orders"
+msgstr ""
+
+#: src/paths/instance/orders/list/Table.tsx:242
+#, c-format
+msgid "No orders have been found matching your query!"
+msgstr ""
+
+#: src/paths/instance/orders/list/Table.tsx:288
+#, c-format
+msgid "duplicated"
+msgstr ""
+
+#: src/paths/instance/orders/list/Table.tsx:299
+#, c-format
+msgid "invalid format"
+msgstr ""
+
+#: src/paths/instance/orders/list/Table.tsx:301
+#, c-format
+msgid "this value exceed the refundable amount"
+msgstr ""
+
+#: src/paths/instance/orders/list/Table.tsx:346
+#, c-format
+msgid "date"
+msgstr ""
+
+#: src/paths/instance/orders/list/Table.tsx:349
+#, c-format
+msgid "amount"
+msgstr ""
+
+#: src/paths/instance/orders/list/Table.tsx:352
+#, c-format
+msgid "reason"
+msgstr ""
+
+#: src/paths/instance/orders/list/Table.tsx:389
+#, c-format
+msgid "amount to be refunded"
+msgstr ""
+
+#: src/paths/instance/orders/list/Table.tsx:391
+#, c-format
+msgid "Max refundable:"
+msgstr ""
+
+#: src/paths/instance/orders/list/Table.tsx:396
+#, c-format
+msgid "Reason"
+msgstr ""
+
+#: src/paths/instance/orders/list/Table.tsx:397
+#, c-format
+msgid "Choose one..."
+msgstr ""
+
+#: src/paths/instance/orders/list/Table.tsx:399
+#, c-format
+msgid "requested by the customer"
+msgstr ""
+
+#: src/paths/instance/orders/list/Table.tsx:400
+#, c-format
+msgid "other"
+msgstr ""
+
+#: src/paths/instance/orders/list/Table.tsx:403
+#, c-format
+msgid "why this order is being refunded"
+msgstr ""
+
+#: src/paths/instance/orders/list/Table.tsx:409
+#, c-format
+msgid "more information to give context"
+msgstr ""
+
+#: src/paths/instance/orders/details/DetailPage.tsx:62
+#, c-format
+msgid "Contract Terms"
+msgstr ""
+
+#: src/paths/instance/orders/details/DetailPage.tsx:68
+#, c-format
+msgid "human-readable description of the whole purchase"
+msgstr ""
+
+#: src/paths/instance/orders/details/DetailPage.tsx:74
+#, c-format
+msgid "total price for the transaction"
+msgstr ""
+
+#: src/paths/instance/orders/details/DetailPage.tsx:81
+#, c-format
+msgid "URL for this purchase"
+msgstr ""
+
+#: src/paths/instance/orders/details/DetailPage.tsx:87
+#, c-format
+msgid "Max fee"
+msgstr ""
+
+#: src/paths/instance/orders/details/DetailPage.tsx:88
+#, c-format
+msgid "maximum total deposit fee accepted by the merchant for this contract"
+msgstr ""
+
+#: src/paths/instance/orders/details/DetailPage.tsx:93
+#, c-format
+msgid "Max wire fee"
+msgstr ""
+
+#: src/paths/instance/orders/details/DetailPage.tsx:94
+#, c-format
+msgid "maximum wire fee accepted by the merchant"
+msgstr ""
+
+#: src/paths/instance/orders/details/DetailPage.tsx:100
+#, c-format
+msgid ""
+"over how many customer transactions does the merchant expect to amortize "
+"wire fees on average"
+msgstr ""
+
+#: src/paths/instance/orders/details/DetailPage.tsx:105
+#, c-format
+msgid "Created at"
+msgstr ""
+
+#: src/paths/instance/orders/details/DetailPage.tsx:106
+#, c-format
+msgid "time when this contract was generated"
+msgstr ""
+
+#: src/paths/instance/orders/details/DetailPage.tsx:112
+#, c-format
+msgid "after this deadline has passed no refunds will be accepted"
+msgstr ""
+
+#: src/paths/instance/orders/details/DetailPage.tsx:118
+#, c-format
+msgid ""
+"after this deadline, the merchant won't accept payments for the contract"
+msgstr ""
+
+#: src/paths/instance/orders/details/DetailPage.tsx:124
+#, c-format
+msgid "transfer deadline for the exchange"
+msgstr ""
+
+#: src/paths/instance/orders/details/DetailPage.tsx:130
+#, c-format
+msgid "time indicating when the order should be delivered"
+msgstr ""
+
+#: src/paths/instance/orders/details/DetailPage.tsx:136
+#, c-format
+msgid "where the order will be delivered"
+msgstr ""
+
+#: src/paths/instance/orders/details/DetailPage.tsx:144
+#, c-format
+msgid "Auto-refund delay"
+msgstr ""
+
+#: src/paths/instance/orders/details/DetailPage.tsx:145
+#, c-format
+msgid ""
+"how long the wallet should try to get an automatic refund for the purchase"
+msgstr ""
+
+#: src/paths/instance/orders/details/DetailPage.tsx:150
+#, c-format
+msgid "Extra info"
+msgstr ""
+
+#: src/paths/instance/orders/details/DetailPage.tsx:151
+#, c-format
+msgid "extra data that is only interpreted by the merchant frontend"
+msgstr ""
+
+#: src/paths/instance/orders/details/DetailPage.tsx:219
+#, c-format
+msgid "Order"
+msgstr ""
+
+#: src/paths/instance/orders/details/DetailPage.tsx:221
+#, c-format
+msgid "claimed"
+msgstr ""
+
+#: src/paths/instance/orders/details/DetailPage.tsx:247
+#, c-format
+msgid "claimed at"
+msgstr ""
+
+#: src/paths/instance/orders/details/DetailPage.tsx:265
+#, c-format
+msgid "Timeline"
+msgstr ""
+
+#: src/paths/instance/orders/details/DetailPage.tsx:271
+#, c-format
+msgid "Payment details"
+msgstr ""
+
+#: src/paths/instance/orders/details/DetailPage.tsx:291
+#, c-format
+msgid "Order status"
+msgstr ""
+
+#: src/paths/instance/orders/details/DetailPage.tsx:301
+#, c-format
+msgid "Product list"
+msgstr ""
+
+#: src/paths/instance/orders/details/DetailPage.tsx:451
+#, c-format
+msgid "paid"
+msgstr ""
+
+#: src/paths/instance/orders/details/DetailPage.tsx:455
+#, c-format
+msgid "wired"
+msgstr ""
+
+#: src/paths/instance/orders/details/DetailPage.tsx:460
+#, c-format
+msgid "refunded"
+msgstr ""
+
+#: src/paths/instance/orders/details/DetailPage.tsx:480
+#, c-format
+msgid "refund order"
+msgstr ""
+
+#: src/paths/instance/orders/details/DetailPage.tsx:481
+#, c-format
+msgid "not refundable"
+msgstr ""
+
+#: src/paths/instance/orders/details/DetailPage.tsx:489
+#, c-format
+msgid "refund"
+msgstr ""
+
+#: src/paths/instance/orders/details/DetailPage.tsx:553
+#, c-format
+msgid "Refunded amount"
+msgstr ""
+
+#: src/paths/instance/orders/details/DetailPage.tsx:560
+#, c-format
+msgid "Refund taken"
+msgstr ""
+
+#: src/paths/instance/orders/details/DetailPage.tsx:570
+#, c-format
+msgid "Status URL"
+msgstr ""
+
+#: src/paths/instance/orders/details/DetailPage.tsx:583
+#, c-format
+msgid "Refund URI"
+msgstr ""
+
+#: src/paths/instance/orders/details/DetailPage.tsx:636
+#, c-format
+msgid "unpaid"
+msgstr ""
+
+#: src/paths/instance/orders/details/DetailPage.tsx:654
+#, c-format
+msgid "pay at"
+msgstr ""
+
+#: src/paths/instance/orders/details/DetailPage.tsx:666
+#, c-format
+msgid "created at"
+msgstr ""
+
+#: src/paths/instance/orders/details/DetailPage.tsx:707
+#, c-format
+msgid "Order status URL"
+msgstr ""
+
+#: src/paths/instance/orders/details/DetailPage.tsx:711
+#, c-format
+msgid "Payment URI"
+msgstr ""
+
+#: src/paths/instance/orders/details/DetailPage.tsx:740
+#, c-format
+msgid ""
+"Unknown order status. This is an error, please contact the administrator."
+msgstr ""
+
+#: src/paths/instance/orders/details/DetailPage.tsx:767
+#, c-format
+msgid "Back"
+msgstr ""
+
+#: src/paths/instance/orders/details/index.tsx:79
+#, c-format
+msgid "refund created successfully"
+msgstr ""
+
+#: src/paths/instance/orders/details/index.tsx:85
+#, c-format
+msgid "could not create the refund"
+msgstr ""
+
+#: src/paths/instance/orders/list/ListPage.tsx:78
+#, c-format
+msgid "select date to show nearby orders"
+msgstr ""
+
+#: src/paths/instance/orders/list/ListPage.tsx:94
+#, c-format
+msgid "order id"
+msgstr ""
+
+#: src/paths/instance/orders/list/ListPage.tsx:100
+#, c-format
+msgid "jump to order with the given order ID"
+msgstr ""
+
+#: src/paths/instance/orders/list/ListPage.tsx:122
+#, c-format
+msgid "remove all filters"
+msgstr ""
+
+#: src/paths/instance/orders/list/ListPage.tsx:132
+#, c-format
+msgid "only show paid orders"
+msgstr ""
+
+#: src/paths/instance/orders/list/ListPage.tsx:135
+#, c-format
+msgid "Paid"
+msgstr ""
+
+#: src/paths/instance/orders/list/ListPage.tsx:142
+#, c-format
+msgid "only show orders with refunds"
+msgstr ""
+
+#: src/paths/instance/orders/list/ListPage.tsx:145
+#, c-format
+msgid "Refunded"
+msgstr ""
+
+#: src/paths/instance/orders/list/ListPage.tsx:152
+#, c-format
+msgid ""
+"only show orders where customers paid, but wire payments from payment "
+"provider are still pending"
+msgstr ""
+
+#: src/paths/instance/orders/list/ListPage.tsx:155
+#, c-format
+msgid "Not wired"
+msgstr ""
+
+#: src/paths/instance/orders/list/ListPage.tsx:170
+#, c-format
+msgid "clear date filter"
+msgstr ""
+
+#: src/paths/instance/orders/list/ListPage.tsx:184
+#, c-format
+msgid "date (YYYY/MM/DD)"
+msgstr ""
+
+#: src/paths/instance/orders/list/index.tsx:103
+#, c-format
+msgid "Enter an order id"
+msgstr ""
+
+#: src/paths/instance/orders/list/index.tsx:111
+#, c-format
+msgid "order not found"
+msgstr ""
+
+#: src/paths/instance/orders/list/index.tsx:178
+#, c-format
+msgid "could not get the order to refund"
+msgstr ""
+
+#: src/components/exception/AsyncButton.tsx:43
+#, c-format
+msgid "Loading..."
+msgstr ""
+
+#: src/components/form/InputStock.tsx:99
+#, c-format
+msgid ""
+"click here to configure the stock of the product, leave it as is and the "
+"backend will not control stock"
+msgstr ""
+
+#: src/components/form/InputStock.tsx:109
+#, c-format
+msgid "Manage stock"
+msgstr ""
+
+#: src/components/form/InputStock.tsx:115
+#, c-format
+msgid "this product has been configured without stock control"
+msgstr ""
+
+#: src/components/form/InputStock.tsx:119
+#, c-format
+msgid "Infinite"
+msgstr ""
+
+#: src/components/form/InputStock.tsx:136
+#, c-format
+msgid "lost cannot be greater than current and incoming (max %1$s)"
+msgstr ""
+
+#: src/components/form/InputStock.tsx:176
+#, c-format
+msgid "Incoming"
+msgstr ""
+
+#: src/components/form/InputStock.tsx:177
+#, c-format
+msgid "Lost"
+msgstr ""
+
+#: src/components/form/InputStock.tsx:192
+#, c-format
+msgid "Current"
+msgstr ""
+
+#: src/components/form/InputStock.tsx:196
+#, c-format
+msgid "remove stock control for this product"
+msgstr ""
+
+#: src/components/form/InputStock.tsx:202
+#, c-format
+msgid "without stock"
+msgstr ""
+
+#: src/components/form/InputStock.tsx:211
+#, c-format
+msgid "Next restock"
+msgstr ""
+
+#: src/components/form/InputStock.tsx:217
+#, c-format
+msgid "Delivery address"
+msgstr ""
+
+#: src/components/product/ProductForm.tsx:133
+#, c-format
+msgid "product identification to use in URLs (for internal use only)"
+msgstr ""
+
+#: src/components/product/ProductForm.tsx:139
+#, c-format
+msgid "illustration of the product for customers"
+msgstr ""
+
+#: src/components/product/ProductForm.tsx:145
+#, c-format
+msgid "product description for customers"
+msgstr ""
+
+#: src/components/product/ProductForm.tsx:149
+#, c-format
+msgid "Age restricted"
+msgstr ""
+
+#: src/components/product/ProductForm.tsx:150
+#, c-format
+msgid "is this product restricted for customer below certain age?"
+msgstr ""
+
+#: src/components/product/ProductForm.tsx:155
+#, c-format
+msgid ""
+"unit describing quantity of product sold (e.g. 2 kilograms, 5 liters, 3 "
+"items, 5 meters) for customers"
+msgstr ""
+
+#: src/components/product/ProductForm.tsx:160
+#, c-format
+msgid ""
+"sale price for customers, including taxes, for above units of the product"
+msgstr ""
+
+#: src/components/product/ProductForm.tsx:164
+#, c-format
+msgid "Stock"
+msgstr ""
+
+#: src/components/product/ProductForm.tsx:166
+#, c-format
+msgid ""
+"product inventory for products with finite supply (for internal use only)"
+msgstr ""
+
+#: src/components/product/ProductForm.tsx:171
+#, c-format
+msgid "taxes included in the product price, exposed to customers"
+msgstr ""
+
+#: src/paths/instance/products/create/CreatePage.tsx:66
+#, c-format
+msgid "Need to complete marked fields"
+msgstr ""
+
+#: src/paths/instance/products/create/index.tsx:51
+#, c-format
+msgid "could not create product"
+msgstr ""
+
+#: src/paths/instance/products/list/Table.tsx:68
+#, c-format
+msgid "Products"
+msgstr ""
+
+#: src/paths/instance/products/list/Table.tsx:73
+#, c-format
+msgid "add product to inventory"
+msgstr ""
+
+#: src/paths/instance/products/list/Table.tsx:137
+#, c-format
+msgid "Sell"
+msgstr ""
+
+#: src/paths/instance/products/list/Table.tsx:143
+#, c-format
+msgid "Profit"
+msgstr ""
+
+#: src/paths/instance/products/list/Table.tsx:149
+#, c-format
+msgid "Sold"
+msgstr ""
+
+#: src/paths/instance/products/list/Table.tsx:210
+#, c-format
+msgid "free"
+msgstr ""
+
+#: src/paths/instance/products/list/Table.tsx:248
+#, c-format
+msgid "go to product update page"
+msgstr ""
+
+#: src/paths/instance/products/list/Table.tsx:255
+#, c-format
+msgid "Update"
+msgstr ""
+
+#: src/paths/instance/products/list/Table.tsx:260
+#, c-format
+msgid "remove this product from the database"
+msgstr ""
+
+#: src/paths/instance/products/list/Table.tsx:331
+#, c-format
+msgid "update the product with new price"
+msgstr ""
+
+#: src/paths/instance/products/list/Table.tsx:341
+#, c-format
+msgid "update product with new price"
+msgstr ""
+
+#: src/paths/instance/products/list/Table.tsx:399
+#, c-format
+msgid "add more elements to the inventory"
+msgstr ""
+
+#: src/paths/instance/products/list/Table.tsx:404
+#, c-format
+msgid "report elements lost in the inventory"
+msgstr ""
+
+#: src/paths/instance/products/list/Table.tsx:409
+#, c-format
+msgid "new price for the product"
+msgstr ""
+
+#: src/paths/instance/products/list/Table.tsx:421
+#, c-format
+msgid "the are value with errors"
+msgstr ""
+
+#: src/paths/instance/products/list/Table.tsx:422
+#, c-format
+msgid "update product with new stock and price"
+msgstr ""
+
+#: src/paths/instance/products/list/Table.tsx:463
+#, c-format
+msgid "There is no products yet, add more pressing the + sign"
+msgstr ""
+
+#: src/paths/instance/products/list/index.tsx:86
+#, c-format
+msgid "product updated successfully"
+msgstr ""
+
+#: src/paths/instance/products/list/index.tsx:92
+#, c-format
+msgid "could not update the product"
+msgstr ""
+
+#: src/paths/instance/products/list/index.tsx:103
+#, c-format
+msgid "product delete successfully"
+msgstr ""
+
+#: src/paths/instance/products/list/index.tsx:109
+#, c-format
+msgid "could not delete the product"
+msgstr ""
+
+#: src/paths/instance/products/update/UpdatePage.tsx:56
+#, c-format
+msgid "Product id:"
+msgstr ""
+
+#: src/paths/instance/reserves/create/CreatedSuccessfully.tsx:95
+#, c-format
+msgid ""
+"To complete the setup of the reserve, you must now initiate a wire transfer "
+"using the given wire transfer subject and crediting the specified amount to "
+"the indicated account of the exchange."
+msgstr ""
+
+#: src/paths/instance/reserves/create/CreatedSuccessfully.tsx:102
+#, c-format
+msgid "If your system supports RFC 8905, you can do this by opening this URI:"
+msgstr ""
+
+#: src/paths/instance/reserves/create/CreatePage.tsx:83
+#, c-format
+msgid "it should be greater than 0"
+msgstr ""
+
+#: src/paths/instance/reserves/create/CreatePage.tsx:88
+#, c-format
+msgid "must be a valid URL"
+msgstr ""
+
+#: src/paths/instance/reserves/create/CreatePage.tsx:107
+#, c-format
+msgid "Initial balance"
+msgstr ""
+
+#: src/paths/instance/reserves/create/CreatePage.tsx:108
+#, c-format
+msgid "balance prior to deposit"
+msgstr ""
+
+#: src/paths/instance/reserves/create/CreatePage.tsx:112
+#, c-format
+msgid "Exchange URL"
+msgstr ""
+
+#: src/paths/instance/reserves/create/CreatePage.tsx:113
+#, c-format
+msgid "URL of exchange"
+msgstr ""
+
+#: src/paths/instance/reserves/create/CreatePage.tsx:148
+#, c-format
+msgid "Next"
+msgstr ""
+
+#: src/paths/instance/reserves/create/CreatePage.tsx:186
+#, c-format
+msgid "Wire method"
+msgstr ""
+
+#: src/paths/instance/reserves/create/CreatePage.tsx:187
+#, c-format
+msgid "method to use for wire transfer"
+msgstr ""
+
+#: src/paths/instance/reserves/create/CreatePage.tsx:189
+#, c-format
+msgid "Select one wire method"
+msgstr ""
+
+#: src/paths/instance/reserves/create/index.tsx:62
+#, c-format
+msgid "could not create reserve"
+msgstr ""
+
+#: src/paths/instance/reserves/details/DetailPage.tsx:77
+#, c-format
+msgid "Valid until"
+msgstr ""
+
+#: src/paths/instance/reserves/details/DetailPage.tsx:82
+#, c-format
+msgid "Created balance"
+msgstr ""
+
+#: src/paths/instance/reserves/details/DetailPage.tsx:99
+#, c-format
+msgid "Exchange balance"
+msgstr ""
+
+#: src/paths/instance/reserves/details/DetailPage.tsx:104
+#, c-format
+msgid "Picked up"
+msgstr ""
+
+#: src/paths/instance/reserves/details/DetailPage.tsx:109
+#, c-format
+msgid "Committed"
+msgstr ""
+
+#: src/paths/instance/reserves/details/DetailPage.tsx:116
+#, c-format
+msgid "Account address"
+msgstr ""
+
+#: src/paths/instance/reserves/details/DetailPage.tsx:119
+#, c-format
+msgid "Subject"
+msgstr ""
+
+#: src/paths/instance/reserves/details/DetailPage.tsx:130
+#, c-format
+msgid "Tips"
+msgstr ""
+
+#: src/paths/instance/reserves/details/DetailPage.tsx:193
+#, c-format
+msgid "No tips has been authorized from this reserve"
+msgstr ""
+
+#: src/paths/instance/reserves/details/DetailPage.tsx:213
+#, c-format
+msgid "Authorized"
+msgstr ""
+
+#: src/paths/instance/reserves/details/DetailPage.tsx:222
+#, c-format
+msgid "Expiration"
+msgstr ""
+
+#: src/paths/instance/reserves/list/AutorizeTipModal.tsx:108
+#, c-format
+msgid "amount of tip"
+msgstr ""
+
+#: src/paths/instance/reserves/list/AutorizeTipModal.tsx:112
+#, c-format
+msgid "Justification"
+msgstr ""
+
+#: src/paths/instance/reserves/list/AutorizeTipModal.tsx:114
+#, c-format
+msgid "reason for the tip"
+msgstr ""
+
+#: src/paths/instance/reserves/list/AutorizeTipModal.tsx:118
+#, c-format
+msgid "URL after tip"
+msgstr ""
+
+#: src/paths/instance/reserves/list/AutorizeTipModal.tsx:119
+#, c-format
+msgid "URL to visit after tip payment"
+msgstr ""
+
+#: src/paths/instance/reserves/list/Table.tsx:65
+#, c-format
+msgid "Reserves not yet funded"
+msgstr ""
+
+#: src/paths/instance/reserves/list/Table.tsx:89
+#, c-format
+msgid "Reserves ready"
+msgstr ""
+
+#: src/paths/instance/reserves/list/Table.tsx:95
+#, c-format
+msgid "add new reserve"
+msgstr ""
+
+#: src/paths/instance/reserves/list/Table.tsx:143
+#, c-format
+msgid "Expires at"
+msgstr ""
+
+#: src/paths/instance/reserves/list/Table.tsx:146
+#, c-format
+msgid "Initial"
+msgstr ""
+
+#: src/paths/instance/reserves/list/Table.tsx:202
+#, c-format
+msgid "delete selected reserve from the database"
+msgstr ""
+
+#: src/paths/instance/reserves/list/Table.tsx:210
+#, c-format
+msgid "authorize new tip from selected reserve"
+msgstr ""
+
+#: src/paths/instance/reserves/list/Table.tsx:237
+#, c-format
+msgid ""
+"There is no ready reserves yet, add more pressing the + sign or fund them"
+msgstr ""
+
+#: src/paths/instance/reserves/list/Table.tsx:264
+#, c-format
+msgid "Expected Balance"
+msgstr ""
+
+#: src/paths/instance/reserves/list/index.tsx:110
+#, c-format
+msgid "could not create the tip"
+msgstr ""
+
+#: src/paths/instance/templates/create/CreatePage.tsx:77
+#, c-format
+msgid "should not be empty"
+msgstr ""
+
+#: src/paths/instance/templates/create/CreatePage.tsx:93
+#, c-format
+msgid "should be greater that 0"
+msgstr ""
+
+#: src/paths/instance/templates/create/CreatePage.tsx:96
+#, c-format
+msgid "can't be empty"
+msgstr ""
+
+#: src/paths/instance/templates/create/CreatePage.tsx:100
+#, c-format
+msgid "to short"
+msgstr ""
+
+#: src/paths/instance/templates/create/CreatePage.tsx:108
+#, c-format
+msgid "just letters and numbers from 2 to 7"
+msgstr ""
+
+#: src/paths/instance/templates/create/CreatePage.tsx:110
+#, c-format
+msgid "size of the key should be 32"
+msgstr ""
+
+#: src/paths/instance/templates/create/CreatePage.tsx:137
+#, c-format
+msgid "Identifier"
+msgstr ""
+
+#: src/paths/instance/templates/create/CreatePage.tsx:138
+#, c-format
+msgid "Name of the template in URLs."
+msgstr ""
+
+#: src/paths/instance/templates/create/CreatePage.tsx:144
+#, c-format
+msgid "Describe what this template stands for"
+msgstr ""
+
+#: src/paths/instance/templates/create/CreatePage.tsx:149
+#, c-format
+msgid "Fixed summary"
+msgstr ""
+
+#: src/paths/instance/templates/create/CreatePage.tsx:150
+#, c-format
+msgid "If specified, this template will create order with the same summary"
+msgstr ""
+
+#: src/paths/instance/templates/create/CreatePage.tsx:154
+#, c-format
+msgid "Fixed price"
+msgstr ""
+
+#: src/paths/instance/templates/create/CreatePage.tsx:155
+#, c-format
+msgid "If specified, this template will create order with the same price"
+msgstr ""
+
+#: src/paths/instance/templates/create/CreatePage.tsx:159
+#, c-format
+msgid "Minimum age"
+msgstr ""
+
+#: src/paths/instance/templates/create/CreatePage.tsx:161
+#, c-format
+msgid "Is this contract restricted to some age?"
+msgstr ""
+
+#: src/paths/instance/templates/create/CreatePage.tsx:165
+#, c-format
+msgid "Payment timeout"
+msgstr ""
+
+#: src/paths/instance/templates/create/CreatePage.tsx:167
+#, c-format
+msgid ""
+"How much time has the customer to complete the payment once the order was "
+"created."
+msgstr ""
+
+#: src/paths/instance/templates/create/CreatePage.tsx:171
+#, c-format
+msgid "Verification algorithm"
+msgstr ""
+
+#: src/paths/instance/templates/create/CreatePage.tsx:172
+#, c-format
+msgid "Algorithm to use to verify transaction in offline mode"
+msgstr ""
+
+#: src/paths/instance/templates/create/CreatePage.tsx:180
+#, c-format
+msgid "Point-of-sale key"
+msgstr ""
+
+#: src/paths/instance/templates/create/CreatePage.tsx:182
+#, c-format
+msgid "Useful to validate the purchase"
+msgstr ""
+
+#: src/paths/instance/templates/create/CreatePage.tsx:196
+#, c-format
+msgid "generate random secret key"
+msgstr ""
+
+#: src/paths/instance/templates/create/CreatePage.tsx:203
+#, c-format
+msgid "random"
+msgstr ""
+
+#: src/paths/instance/templates/create/CreatePage.tsx:208
+#, c-format
+msgid "show secret key"
+msgstr ""
+
+#: src/paths/instance/templates/create/CreatePage.tsx:209
+#, c-format
+msgid "hide secret key"
+msgstr ""
+
+#: src/paths/instance/templates/create/CreatePage.tsx:216
+#, c-format
+msgid "hide"
+msgstr ""
+
+#: src/paths/instance/templates/create/CreatePage.tsx:218
+#, c-format
+msgid "show"
+msgstr ""
+
+#: src/paths/instance/templates/create/index.tsx:52
+#, c-format
+msgid "could not inform template"
+msgstr ""
+
+#: src/paths/instance/templates/use/UsePage.tsx:54
+#, c-format
+msgid "Amount is required"
+msgstr ""
+
+#: src/paths/instance/templates/use/UsePage.tsx:58
+#, c-format
+msgid "Order summary is required"
+msgstr ""
+
+#: src/paths/instance/templates/use/UsePage.tsx:86
+#, c-format
+msgid "New order for template"
+msgstr ""
+
+#: src/paths/instance/templates/use/UsePage.tsx:108
+#, c-format
+msgid "Amount of the order"
+msgstr ""
+
+#: src/paths/instance/templates/use/UsePage.tsx:113
+#, c-format
+msgid "Order summary"
+msgstr ""
+
+#: src/paths/instance/templates/use/index.tsx:92
+#, c-format
+msgid "could not create order from template"
+msgstr ""
+
+#: src/paths/instance/templates/qr/QrPage.tsx:131
+#, c-format
+msgid ""
+"Here you can specify a default value for fields that are not fixed. Default "
+"values can be edited by the customer before the payment."
+msgstr ""
+
+#: src/paths/instance/templates/qr/QrPage.tsx:148
+#, c-format
+msgid "Fixed amount"
+msgstr ""
+
+#: src/paths/instance/templates/qr/QrPage.tsx:149
+#, c-format
+msgid "Default amount"
+msgstr ""
+
+#: src/paths/instance/templates/qr/QrPage.tsx:161
+#, c-format
+msgid "Default summary"
+msgstr ""
+
+#: src/paths/instance/templates/qr/QrPage.tsx:177
+#, c-format
+msgid "Print"
+msgstr ""
+
+#: src/paths/instance/templates/qr/QrPage.tsx:184
+#, c-format
+msgid "Setup TOTP"
+msgstr ""
+
+#: src/paths/instance/templates/list/Table.tsx:65
+#, c-format
+msgid "Templates"
+msgstr ""
+
+#: src/paths/instance/templates/list/Table.tsx:70
+#, c-format
+msgid "add new templates"
+msgstr ""
+
+#: src/paths/instance/templates/list/Table.tsx:142
+#, c-format
+msgid "load more templates before the first one"
+msgstr ""
+
+#: src/paths/instance/templates/list/Table.tsx:146
+#, c-format
+msgid "load newer templates"
+msgstr ""
+
+#: src/paths/instance/templates/list/Table.tsx:181
+#, c-format
+msgid "delete selected templates from the database"
+msgstr ""
+
+#: src/paths/instance/templates/list/Table.tsx:188
+#, c-format
+msgid "use template to create new order"
+msgstr ""
+
+#: src/paths/instance/templates/list/Table.tsx:195
+#, c-format
+msgid "create qr code for the template"
+msgstr ""
+
+#: src/paths/instance/templates/list/Table.tsx:210
+#, c-format
+msgid "load more templates after the last one"
+msgstr ""
+
+#: src/paths/instance/templates/list/Table.tsx:214
+#, c-format
+msgid "load older templates"
+msgstr ""
+
+#: src/paths/instance/templates/list/Table.tsx:231
+#, c-format
+msgid "There is no templates yet, add more pressing the + sign"
+msgstr ""
+
+#: src/paths/instance/templates/list/index.tsx:104
+#, c-format
+msgid "template delete successfully"
+msgstr ""
+
+#: src/paths/instance/templates/list/index.tsx:110
+#, c-format
+msgid "could not delete the template"
+msgstr ""
+
+#: src/paths/instance/templates/update/index.tsx:90
+#, c-format
+msgid "could not update template"
+msgstr ""
+
+#: src/paths/instance/webhooks/create/CreatePage.tsx:57
+#, c-format
+msgid "should be one of '%1$s'"
+msgstr ""
+
+#: src/paths/instance/webhooks/create/CreatePage.tsx:85
+#, c-format
+msgid "Webhook ID to use"
+msgstr ""
+
+#: src/paths/instance/webhooks/create/CreatePage.tsx:89
+#, c-format
+msgid "Event"
+msgstr ""
+
+#: src/paths/instance/webhooks/create/CreatePage.tsx:90
+#, c-format
+msgid "The event of the webhook: why the webhook is used"
+msgstr ""
+
+#: src/paths/instance/webhooks/create/CreatePage.tsx:94
+#, c-format
+msgid "Method"
+msgstr ""
+
+#: src/paths/instance/webhooks/create/CreatePage.tsx:95
+#, c-format
+msgid "Method used by the webhook"
+msgstr ""
+
+#: src/paths/instance/webhooks/create/CreatePage.tsx:99
+#, c-format
+msgid "URL"
+msgstr ""
+
+#: src/paths/instance/webhooks/create/CreatePage.tsx:100
+#, c-format
+msgid "URL of the webhook where the customer will be redirected"
+msgstr ""
+
+#: src/paths/instance/webhooks/create/CreatePage.tsx:104
+#, c-format
+msgid "Header"
+msgstr ""
+
+#: src/paths/instance/webhooks/create/CreatePage.tsx:106
+#, c-format
+msgid "Header template of the webhook"
+msgstr ""
+
+#: src/paths/instance/webhooks/create/CreatePage.tsx:111
+#, c-format
+msgid "Body"
+msgstr ""
+
+#: src/paths/instance/webhooks/create/CreatePage.tsx:112
+#, c-format
+msgid "Body template by the webhook"
+msgstr ""
+
+#: src/paths/instance/webhooks/list/Table.tsx:61
+#, c-format
+msgid "Webhooks"
+msgstr ""
+
+#: src/paths/instance/webhooks/list/Table.tsx:66
+#, c-format
+msgid "add new webhooks"
+msgstr ""
+
+#: src/paths/instance/webhooks/list/Table.tsx:137
+#, c-format
+msgid "load more webhooks before the first one"
+msgstr ""
+
+#: src/paths/instance/webhooks/list/Table.tsx:141
+#, c-format
+msgid "load newer webhooks"
+msgstr ""
+
+#: src/paths/instance/webhooks/list/Table.tsx:151
+#, c-format
+msgid "Event type"
+msgstr ""
+
+#: src/paths/instance/webhooks/list/Table.tsx:176
+#, c-format
+msgid "delete selected webhook from the database"
+msgstr ""
+
+#: src/paths/instance/webhooks/list/Table.tsx:198
+#, c-format
+msgid "load more webhooks after the last one"
+msgstr ""
+
+#: src/paths/instance/webhooks/list/Table.tsx:202
+#, c-format
+msgid "load older webhooks"
+msgstr ""
+
+#: src/paths/instance/webhooks/list/Table.tsx:219
+#, c-format
+msgid "There is no webhooks yet, add more pressing the + sign"
+msgstr ""
+
+#: src/paths/instance/webhooks/list/index.tsx:94
+#, c-format
+msgid "webhook delete successfully"
+msgstr ""
+
+#: src/paths/instance/webhooks/list/index.tsx:100
+#, c-format
+msgid "could not delete the webhook"
+msgstr ""
+
+#: src/paths/instance/transfers/create/CreatePage.tsx:63
+#, c-format
+msgid "check the id, does not look valid"
+msgstr ""
+
+#: src/paths/instance/transfers/create/CreatePage.tsx:65
+#, c-format
+msgid "should have 52 characters, current %1$s"
+msgstr ""
+
+#: src/paths/instance/transfers/create/CreatePage.tsx:72
+#, c-format
+msgid "URL doesn't have the right format"
+msgstr ""
+
+#: src/paths/instance/transfers/create/CreatePage.tsx:98
+#, c-format
+msgid "Credited bank account"
+msgstr ""
+
+#: src/paths/instance/transfers/create/CreatePage.tsx:100
+#, c-format
+msgid "Select one account"
+msgstr ""
+
+#: src/paths/instance/transfers/create/CreatePage.tsx:101
+#, c-format
+msgid "Bank account of the merchant where the payment was received"
+msgstr ""
+
+#: src/paths/instance/transfers/create/CreatePage.tsx:105
+#, c-format
+msgid "Wire transfer ID"
+msgstr ""
+
+#: src/paths/instance/transfers/create/CreatePage.tsx:107
+#, c-format
+msgid ""
+"unique identifier of the wire transfer used by the exchange, must be 52 "
+"characters long"
+msgstr ""
+
+#: src/paths/instance/transfers/create/CreatePage.tsx:112
+#, c-format
+msgid ""
+"Base URL of the exchange that made the transfer, should have been in the "
+"wire transfer subject"
+msgstr ""
+
+#: src/paths/instance/transfers/create/CreatePage.tsx:117
+#, c-format
+msgid "Amount credited"
+msgstr ""
+
+#: src/paths/instance/transfers/create/CreatePage.tsx:118
+#, c-format
+msgid "Actual amount that was wired to the merchant's bank account"
+msgstr ""
+
+#: src/paths/instance/transfers/create/index.tsx:58
+#, c-format
+msgid "could not inform transfer"
+msgstr ""
+
+#: src/paths/instance/transfers/list/Table.tsx:61
+#, c-format
+msgid "Transfers"
+msgstr ""
+
+#: src/paths/instance/transfers/list/Table.tsx:66
+#, c-format
+msgid "add new transfer"
+msgstr ""
+
+#: src/paths/instance/transfers/list/Table.tsx:129
+#, c-format
+msgid "load more transfers before the first one"
+msgstr ""
+
+#: src/paths/instance/transfers/list/Table.tsx:133
+#, c-format
+msgid "load newer transfers"
+msgstr ""
+
+#: src/paths/instance/transfers/list/Table.tsx:143
+#, c-format
+msgid "Credit"
+msgstr ""
+
+#: src/paths/instance/transfers/list/Table.tsx:152
+#, c-format
+msgid "Confirmed"
+msgstr ""
+
+#: src/paths/instance/transfers/list/Table.tsx:155
+#, c-format
+msgid "Verified"
+msgstr ""
+
+#: src/paths/instance/transfers/list/Table.tsx:158
+#, c-format
+msgid "Executed at"
+msgstr ""
+
+#: src/paths/instance/transfers/list/Table.tsx:171
+#, c-format
+msgid "yes"
+msgstr ""
+
+#: src/paths/instance/transfers/list/Table.tsx:171
+#, c-format
+msgid "no"
+msgstr ""
+
+#: src/paths/instance/transfers/list/Table.tsx:181
+#, c-format
+msgid "unknown"
+msgstr ""
+
+#: src/paths/instance/transfers/list/Table.tsx:187
+#, c-format
+msgid "delete selected transfer from the database"
+msgstr ""
+
+#: src/paths/instance/transfers/list/Table.tsx:202
+#, c-format
+msgid "load more transfer after the last one"
+msgstr ""
+
+#: src/paths/instance/transfers/list/Table.tsx:206
+#, c-format
+msgid "load older transfers"
+msgstr ""
+
+#: src/paths/instance/transfers/list/Table.tsx:223
+#, c-format
+msgid "There is no transfer yet, add more pressing the + sign"
+msgstr ""
+
+#: src/paths/instance/transfers/list/ListPage.tsx:79
+#, c-format
+msgid "filter by account address"
+msgstr ""
+
+#: src/paths/instance/transfers/list/ListPage.tsx:100
+#, c-format
+msgid "only show wire transfers confirmed by the merchant"
+msgstr ""
+
+#: src/paths/instance/transfers/list/ListPage.tsx:110
+#, c-format
+msgid "only show wire transfers claimed by the exchange"
+msgstr ""
+
+#: src/paths/instance/transfers/list/ListPage.tsx:113
+#, c-format
+msgid "Unverified"
+msgstr ""
+
+#: src/paths/admin/create/CreatePage.tsx:69
+#, c-format
+msgid "is not valid"
+msgstr ""
+
+#: src/paths/admin/create/CreatePage.tsx:94
+#, c-format
+msgid "is not a number"
+msgstr ""
+
+#: src/paths/admin/create/CreatePage.tsx:96
+#, c-format
+msgid "must be 1 or greater"
+msgstr ""
+
+#: src/paths/admin/create/CreatePage.tsx:107
+#, c-format
+msgid "max 7 lines"
+msgstr ""
+
+#: src/paths/admin/create/CreatePage.tsx:178
+#, c-format
+msgid "change authorization configuration"
+msgstr ""
+
+#: src/paths/admin/create/CreatePage.tsx:217
+#, c-format
+msgid "Need to complete marked fields and choose authorization method"
+msgstr ""
+
+#: src/components/form/InputPaytoForm.tsx:82
+#, c-format
+msgid "This is not a valid bitcoin address."
+msgstr ""
+
+#: src/components/form/InputPaytoForm.tsx:95
+#, c-format
+msgid "This is not a valid Ethereum address."
+msgstr ""
+
+#: src/components/form/InputPaytoForm.tsx:118
+#, c-format
+msgid "IBAN numbers usually have more that 4 digits"
+msgstr ""
+
+#: src/components/form/InputPaytoForm.tsx:120
+#, c-format
+msgid "IBAN numbers usually have less that 34 digits"
+msgstr ""
+
+#: src/components/form/InputPaytoForm.tsx:128
+#, c-format
+msgid "IBAN country code not found"
+msgstr ""
+
+#: src/components/form/InputPaytoForm.tsx:153
+#, c-format
+msgid "IBAN number is not valid, checksum is wrong"
+msgstr ""
+
+#: src/components/form/InputPaytoForm.tsx:248
+#, c-format
+msgid "Target type"
+msgstr ""
+
+#: src/components/form/InputPaytoForm.tsx:249
+#, c-format
+msgid "Method to use for wire transfer"
+msgstr ""
+
+#: src/components/form/InputPaytoForm.tsx:258
+#, c-format
+msgid "Routing"
+msgstr ""
+
+#: src/components/form/InputPaytoForm.tsx:259
+#, c-format
+msgid "Routing number."
+msgstr ""
+
+#: src/components/form/InputPaytoForm.tsx:263
+#, c-format
+msgid "Account"
+msgstr ""
+
+#: src/components/form/InputPaytoForm.tsx:264
+#, c-format
+msgid "Account number."
+msgstr ""
+
+#: src/components/form/InputPaytoForm.tsx:273
+#, c-format
+msgid "Business Identifier Code."
+msgstr ""
+
+#: src/components/form/InputPaytoForm.tsx:282
+#, c-format
+msgid "Bank Account Number."
+msgstr ""
+
+#: src/components/form/InputPaytoForm.tsx:292
+#, c-format
+msgid "Unified Payment Interface."
+msgstr ""
+
+#: src/components/form/InputPaytoForm.tsx:301
+#, c-format
+msgid "Bitcoin protocol."
+msgstr ""
+
+#: src/components/form/InputPaytoForm.tsx:310
+#, c-format
+msgid "Ethereum protocol."
+msgstr ""
+
+#: src/components/form/InputPaytoForm.tsx:319
+#, c-format
+msgid "Interledger protocol."
+msgstr ""
+
+#: src/components/form/InputPaytoForm.tsx:328
+#, c-format
+msgid "Host"
+msgstr ""
+
+#: src/components/form/InputPaytoForm.tsx:329
+#, c-format
+msgid "Bank host."
+msgstr ""
+
+#: src/components/form/InputPaytoForm.tsx:334
+#, c-format
+msgid "Bank account."
+msgstr ""
+
+#: src/components/form/InputPaytoForm.tsx:343
+#, c-format
+msgid "Bank account owner's name."
+msgstr ""
+
+#: src/components/form/InputPaytoForm.tsx:370
+#, c-format
+msgid "No accounts yet."
+msgstr ""
+
+#: src/components/instance/DefaultInstanceFormFields.tsx:52
+#, c-format
+msgid ""
+"Name of the instance in URLs. The 'default' instance is special in that it "
+"is used to administer other instances."
+msgstr ""
+
+#: src/components/instance/DefaultInstanceFormFields.tsx:58
+#, c-format
+msgid "Business name"
+msgstr ""
+
+#: src/components/instance/DefaultInstanceFormFields.tsx:59
+#, c-format
+msgid "Legal name of the business represented by this instance."
+msgstr ""
+
+#: src/components/instance/DefaultInstanceFormFields.tsx:64
+#, c-format
+msgid "Email"
+msgstr ""
+
+#: src/components/instance/DefaultInstanceFormFields.tsx:65
+#, c-format
+msgid "Contact email"
+msgstr ""
+
+#: src/components/instance/DefaultInstanceFormFields.tsx:70
+#, c-format
+msgid "Website URL"
+msgstr ""
+
+#: src/components/instance/DefaultInstanceFormFields.tsx:71
+#, c-format
+msgid "URL."
+msgstr ""
+
+#: src/components/instance/DefaultInstanceFormFields.tsx:76
+#, c-format
+msgid "Logo"
+msgstr ""
+
+#: src/components/instance/DefaultInstanceFormFields.tsx:77
+#, c-format
+msgid "Logo image."
+msgstr ""
+
+#: src/components/instance/DefaultInstanceFormFields.tsx:82
+#, c-format
+msgid "Bank account"
+msgstr ""
+
+#: src/components/instance/DefaultInstanceFormFields.tsx:83
+#, c-format
+msgid "URI specifying bank account for crediting revenue."
+msgstr ""
+
+#: src/components/instance/DefaultInstanceFormFields.tsx:88
+#, c-format
+msgid "Default max deposit fee"
+msgstr ""
+
+#: src/components/instance/DefaultInstanceFormFields.tsx:89
+#, c-format
+msgid ""
+"Maximum deposit fees this merchant is willing to pay per order by default."
+msgstr ""
+
+#: src/components/instance/DefaultInstanceFormFields.tsx:94
+#, c-format
+msgid "Default max wire fee"
+msgstr ""
+
+#: src/components/instance/DefaultInstanceFormFields.tsx:95
+#, c-format
+msgid ""
+"Maximum wire fees this merchant is willing to pay per wire transfer by "
+"default."
+msgstr ""
+
+#: src/components/instance/DefaultInstanceFormFields.tsx:100
+#, c-format
+msgid "Default wire fee amortization"
+msgstr ""
+
+#: src/components/instance/DefaultInstanceFormFields.tsx:101
+#, c-format
+msgid ""
+"Number of orders excess wire transfer fees will be divided by to compute per "
+"order surcharge."
+msgstr ""
+
+#: src/components/instance/DefaultInstanceFormFields.tsx:107
+#, c-format
+msgid "Physical location of the merchant."
+msgstr ""
+
+#: src/components/instance/DefaultInstanceFormFields.tsx:114
+#, c-format
+msgid "Jurisdiction"
+msgstr ""
+
+#: src/components/instance/DefaultInstanceFormFields.tsx:115
+#, c-format
+msgid "Jurisdiction for legal disputes with the merchant."
+msgstr ""
+
+#: src/components/instance/DefaultInstanceFormFields.tsx:122
+#, c-format
+msgid "Default payment delay"
+msgstr ""
+
+#: src/components/instance/DefaultInstanceFormFields.tsx:124
+#, c-format
+msgid ""
+"Time customers have to pay an order before the offer expires by default."
+msgstr ""
+
+#: src/components/instance/DefaultInstanceFormFields.tsx:129
+#, c-format
+msgid "Default wire transfer delay"
+msgstr ""
+
+#: src/components/instance/DefaultInstanceFormFields.tsx:130
+#, c-format
+msgid ""
+"Maximum time an exchange is allowed to delay wiring funds to the merchant, "
+"enabling it to aggregate smaller payments into larger wire transfers and "
+"reducing wire fees."
+msgstr ""
+
+#: src/paths/instance/update/UpdatePage.tsx:164
+#, c-format
+msgid "Instance id"
+msgstr ""
+
+#: src/paths/instance/update/UpdatePage.tsx:173
+#, c-format
+msgid "Change the authorization method use for this instance."
+msgstr ""
+
+#: src/paths/instance/update/UpdatePage.tsx:182
+#, c-format
+msgid "Manage access token"
+msgstr ""
+
+#: src/paths/instance/update/index.tsx:112
+#, c-format
+msgid "Failed to create instance"
+msgstr ""
+
+#: src/components/exception/login.tsx:74
+#, c-format
+msgid "Login required"
+msgstr ""
+
+#: src/components/exception/login.tsx:80
+#, c-format
+msgid "Please enter your access token."
+msgstr ""
+
+#: src/components/exception/login.tsx:108
+#, c-format
+msgid "Access Token"
+msgstr ""
+
+#: src/InstanceRoutes.tsx:171
+#, c-format
+msgid "The request to the backend take too long and was cancelled"
+msgstr ""
+
+#: src/InstanceRoutes.tsx:172
+#, c-format
+msgid "Diagnostic from %1$s is \"%2$s\""
+msgstr ""
+
+#: src/InstanceRoutes.tsx:178
+#, c-format
+msgid "The backend reported a problem: HTTP status #%1$s"
+msgstr ""
+
+#: src/InstanceRoutes.tsx:179
+#, c-format
+msgid "Diagnostic from %1$s is '%2$s'"
+msgstr ""
+
+#: src/InstanceRoutes.tsx:196
+#, c-format
+msgid "Access denied"
+msgstr ""
+
+#: src/InstanceRoutes.tsx:197
+#, c-format
+msgid "The access token provided is invalid."
+msgstr ""
+
+#: src/InstanceRoutes.tsx:212
+#, c-format
+msgid "No 'default' instance configured yet."
+msgstr ""
+
+#: src/InstanceRoutes.tsx:213
+#, c-format
+msgid "Create a 'default' instance to begin using the merchant backoffice."
+msgstr ""
+
+#: src/InstanceRoutes.tsx:630
+#, c-format
+msgid "The access token provided is invalid"
+msgstr ""
+
+#: src/InstanceRoutes.tsx:664
+#, c-format
+msgid "Hide for today"
+msgstr ""
+
+#: src/components/menu/SideBar.tsx:82
+#, c-format
+msgid "Instance"
+msgstr ""
+
+#: src/components/menu/SideBar.tsx:91
+#, c-format
+msgid "Settings"
+msgstr ""
+
+#: src/components/menu/SideBar.tsx:167
+#, c-format
+msgid "Connection"
+msgstr ""
+
+#: src/components/menu/SideBar.tsx:209
+#, c-format
+msgid "New"
+msgstr ""
+
+#: src/components/menu/SideBar.tsx:219
+#, c-format
+msgid "List"
+msgstr ""
+
+#: src/components/menu/SideBar.tsx:234
+#, c-format
+msgid "Log out"
+msgstr ""
+
+#: src/ApplicationReadyRoutes.tsx:71
+#, c-format
+msgid "Check your token is valid"
+msgstr ""
+
+#: src/ApplicationReadyRoutes.tsx:90
+#, c-format
+msgid "Couldn't access the server."
+msgstr ""
+
+#: src/ApplicationReadyRoutes.tsx:91
+#, c-format
+msgid "Could not infer instance id from url %1$s"
+msgstr ""
+
+#: src/Application.tsx:104
+#, c-format
+msgid "Server not found"
+msgstr ""
+
+#: src/Application.tsx:118
+#, c-format
+msgid "Server response with an error code"
+msgstr ""
+
+#: src/Application.tsx:120
+#, c-format
+msgid "Got message %1$s from %2$s"
+msgstr ""
+
+#: src/Application.tsx:131
+#, c-format
+msgid "Response from server is unreadable, http status: %1$s"
+msgstr ""
+
+#: src/Application.tsx:144
+#, c-format
+msgid "Unexpected Error"
+msgstr ""
+
+#: src/components/form/InputArray.tsx:101
+#, c-format
+msgid "The value %1$s is invalid for a payment url"
+msgstr ""
+
+#: src/components/form/InputArray.tsx:110
+#, c-format
+msgid "add element to the list"
+msgstr ""
+
+#: src/components/form/InputArray.tsx:112
+#, c-format
+msgid "add"
+msgstr ""
+
+#: src/components/form/InputSecured.tsx:37
+#, c-format
+msgid "Deleting"
+msgstr ""
+
+#: src/components/form/InputSecured.tsx:41
+#, c-format
+msgid "Changing"
+msgstr ""
+
+#: src/paths/instance/orders/create/OrderCreatedSuccessfully.tsx:87
+#, c-format
+msgid "Order ID"
+msgstr ""
+
+#: src/paths/instance/orders/create/OrderCreatedSuccessfully.tsx:101
+#, c-format
+msgid "Payment URL"
+msgstr ""
diff --git a/packages/auditor-backoffice-ui/src/i18n/es.po 
b/packages/auditor-backoffice-ui/src/i18n/es.po
new file mode 100644
index 000000000..10ec0cf3b
--- /dev/null
+++ b/packages/auditor-backoffice-ui/src/i18n/es.po
@@ -0,0 +1,2854 @@
+# This file is part of TALER
+# (C) 2016 GNUnet e.V.
+#
+# TALER is free software; you can redistribute it and/or modify it under the
+# terms of the GNU General Public License as published by the Free Software
+# Foundation; either version 3, or (at your option) any later version.
+#
+# TALER is distributed in the hope that it will be useful, but WITHOUT ANY
+# WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
+# A PARTICULAR PURPOSE.  See the GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License along with
+# TALER; see the file COPYING.  If not, see <http://www.gnu.org/licenses/>
+#
+msgid ""
+msgstr ""
+"Project-Id-Version: Taler Wallet\n"
+"Report-Msgid-Bugs-To: taler@gnu.org\n"
+"POT-Creation-Date: 2016-11-23 00:00+0100\n"
+"PO-Revision-Date: 2023-08-13 10:14+0000\n"
+"Last-Translator: Javier Sepulveda <javier.sepulveda@uv.es>\n"
+"Language-Team: Spanish <https://weblate.taler.net/projects/gnu-taler/";
+"merchant-backoffice/es/>\n"
+"Language: es\n"
+"MIME-Version: 1.0\n"
+"Content-Type: text/plain; charset=UTF-8\n"
+"Content-Transfer-Encoding: 8bit\n"
+"Plural-Forms: nplurals=2; plural=n != 1;\n"
+"X-Generator: Weblate 4.13.1\n"
+
+#: src/components/modal/index.tsx:71
+#, c-format
+msgid "Cancel"
+msgstr "Cancelar"
+
+#: src/components/modal/index.tsx:79
+#, c-format
+msgid "%1$s"
+msgstr "%1$s"
+
+#: src/components/modal/index.tsx:84
+#, c-format
+msgid "Close"
+msgstr ""
+
+#: src/components/modal/index.tsx:124
+#, c-format
+msgid "Continue"
+msgstr "Continuar"
+
+#: src/components/modal/index.tsx:178
+#, c-format
+msgid "Clear"
+msgstr "Limpiar"
+
+#: src/components/modal/index.tsx:190
+#, c-format
+msgid "Confirm"
+msgstr "Confirmar"
+
+#: src/components/modal/index.tsx:296
+#, c-format
+msgid "is not the same as the current access token"
+msgstr "no es el mismo que el token de acceso actual"
+
+#: src/components/modal/index.tsx:299
+#, c-format
+msgid "cannot be empty"
+msgstr "no puede ser vacío"
+
+#: src/components/modal/index.tsx:301
+#, c-format
+msgid "cannot be the same as the old token"
+msgstr "no puede ser igual al viejo token"
+
+#: src/components/modal/index.tsx:305
+#, c-format
+msgid "is not the same"
+msgstr "no son iguales"
+
+#: src/components/modal/index.tsx:315
+#, c-format
+msgid "You are updating the access token from instance with id %1$s"
+msgstr "Está actualizando el token de acceso para la instancia con id %1$s"
+
+#: src/components/modal/index.tsx:331
+#, c-format
+msgid "Old access token"
+msgstr "Viejo token de acceso"
+
+#: src/components/modal/index.tsx:332
+#, c-format
+msgid "access token currently in use"
+msgstr "acceder al token en uso actualmente"
+
+#: src/components/modal/index.tsx:338
+#, c-format
+msgid "New access token"
+msgstr "Nuevo token de acceso"
+
+#: src/components/modal/index.tsx:339
+#, c-format
+msgid "next access token to be used"
+msgstr "siguiente token de acceso a usar"
+
+#: src/components/modal/index.tsx:344
+#, c-format
+msgid "Repeat access token"
+msgstr "Repetir token de acceso"
+
+#: src/components/modal/index.tsx:345
+#, c-format
+msgid "confirm the same access token"
+msgstr "confirmar el mismo token de acceso"
+
+#: src/components/modal/index.tsx:350
+#, c-format
+msgid "Clearing the access token will mean public access to the instance"
+msgstr "Limpiar el token de acceso significa acceso público a la instancia"
+
+#: src/components/modal/index.tsx:377
+#, c-format
+msgid "cannot be the same as the old access token"
+msgstr "no puede ser igual al anterior token de acceso"
+
+#: src/components/modal/index.tsx:394
+#, c-format
+msgid "You are setting the access token for the new instance"
+msgstr "Está estableciendo el token de acceso para la nueva instancia"
+
+#: src/components/modal/index.tsx:420
+#, c-format
+msgid ""
+"With external authorization method no check will be done by the merchant "
+"backend"
+msgstr ""
+"Con el método de autorización externa no se hará ninguna revisión por el "
+"backend del comerciante"
+
+#: src/components/modal/index.tsx:436
+#, c-format
+msgid "Set external authorization"
+msgstr "Establecer autorización externa"
+
+#: src/components/modal/index.tsx:448
+#, c-format
+msgid "Set access token"
+msgstr "Establecer token de acceso"
+
+#: src/components/modal/index.tsx:470
+#, c-format
+msgid "Operation in progress..."
+msgstr "Operación en progreso..."
+
+#: src/components/modal/index.tsx:479
+#, c-format
+msgid "The operation will be automatically canceled after %1$s seconds"
+msgstr "La operación será automáticamente cancelada luego de %1$s segundos"
+
+#: src/paths/admin/list/TableActive.tsx:80
+#, c-format
+msgid "Instances"
+msgstr "Instancias"
+
+#: src/paths/admin/list/TableActive.tsx:93
+#, c-format
+msgid "Delete"
+msgstr "Eliminar"
+
+#: src/paths/admin/list/TableActive.tsx:99
+#, c-format
+msgid "add new instance"
+msgstr "agregar nueva instancia"
+
+#: src/paths/admin/list/TableActive.tsx:178
+#, c-format
+msgid "ID"
+msgstr "ID"
+
+#: src/paths/admin/list/TableActive.tsx:181
+#, c-format
+msgid "Name"
+msgstr "Nombre"
+
+#: src/paths/admin/list/TableActive.tsx:220
+#, c-format
+msgid "Edit"
+msgstr "Editar"
+
+#: src/paths/admin/list/TableActive.tsx:237
+#, c-format
+msgid "Purge"
+msgstr "Purgar"
+
+#: src/paths/admin/list/TableActive.tsx:261
+#, c-format
+msgid "There is no instances yet, add more pressing the + sign"
+msgstr "Todavía no hay instancias, agregue más presionando el signo +"
+
+#: src/paths/admin/list/View.tsx:68
+#, c-format
+msgid "Only show active instances"
+msgstr "Solo mostrar instancias activas"
+
+#: src/paths/admin/list/View.tsx:71
+#, c-format
+msgid "Active"
+msgstr "Activo"
+
+#: src/paths/admin/list/View.tsx:78
+#, c-format
+msgid "Only show deleted instances"
+msgstr "Mostrar solo instancias eliminadas"
+
+#: src/paths/admin/list/View.tsx:81
+#, c-format
+msgid "Deleted"
+msgstr "Eliminado"
+
+#: src/paths/admin/list/View.tsx:88
+#, c-format
+msgid "Show all instances"
+msgstr "Mostrar todas las instancias"
+
+#: src/paths/admin/list/View.tsx:91
+#, c-format
+msgid "All"
+msgstr "Todo"
+
+#: src/paths/admin/list/index.tsx:101
+#, fuzzy, c-format
+msgid "Instance \"%1$s\" (ID: %2$s) has been deleted"
+msgstr "La instancia '%1$s' (ID: %2$s) fue eliminada"
+
+#: src/paths/admin/list/index.tsx:106
+#, c-format
+msgid "Failed to delete instance"
+msgstr "Fallo al eliminar instancia"
+
+#: src/paths/admin/list/index.tsx:124
+#, c-format
+msgid "Instance '%1$s' (ID: %2$s) has been disabled"
+msgstr "Instance '%1$s' (ID: %2$s) ha sido deshabilitada"
+
+#: src/paths/admin/list/index.tsx:129
+#, c-format
+msgid "Failed to purge instance"
+msgstr "Fallo al purgar la instancia"
+
+#: src/paths/instance/kyc/list/ListPage.tsx:41
+#, c-format
+msgid "Pending KYC verification"
+msgstr "Verificación KYC pendiente"
+
+#: src/paths/instance/kyc/list/ListPage.tsx:66
+#, c-format
+msgid "Timed out"
+msgstr "Expirado"
+
+#: src/paths/instance/kyc/list/ListPage.tsx:103
+#, c-format
+msgid "Exchange"
+msgstr "Exchange"
+
+#: src/paths/instance/kyc/list/ListPage.tsx:106
+#, c-format
+msgid "Target account"
+msgstr "Cuenta objetivo"
+
+#: src/paths/instance/kyc/list/ListPage.tsx:109
+#, c-format
+msgid "KYC URL"
+msgstr "URL de KYC"
+
+#: src/paths/instance/kyc/list/ListPage.tsx:144
+#, c-format
+msgid "Code"
+msgstr "Código"
+
+#: src/paths/instance/kyc/list/ListPage.tsx:147
+#, c-format
+msgid "Http Status"
+msgstr "Estado http"
+
+#: src/paths/instance/kyc/list/ListPage.tsx:177
+#, c-format
+msgid "No pending kyc verification!"
+msgstr "¡No hay verificación kyc pendiente!"
+
+#: src/components/form/InputDate.tsx:123
+#, c-format
+msgid "change value to unknown date"
+msgstr "cambiar valor a fecha desconocida"
+
+#: src/components/form/InputDate.tsx:124
+#, c-format
+msgid "change value to empty"
+msgstr "cambiar valor a vacío"
+
+#: src/components/form/InputDate.tsx:131
+#, c-format
+msgid "clear"
+msgstr "limpiar"
+
+#: src/components/form/InputDate.tsx:136
+#, c-format
+msgid "change value to never"
+msgstr "cambiar valor a nunca"
+
+#: src/components/form/InputDate.tsx:141
+#, c-format
+msgid "never"
+msgstr "nunca"
+
+#: src/components/form/InputLocation.tsx:29
+#, c-format
+msgid "Country"
+msgstr "País"
+
+#: src/components/form/InputLocation.tsx:33
+#, c-format
+msgid "Address"
+msgstr "Dirección"
+
+#: src/components/form/InputLocation.tsx:39
+#, c-format
+msgid "Building number"
+msgstr "Número de edificio"
+
+#: src/components/form/InputLocation.tsx:41
+#, c-format
+msgid "Building name"
+msgstr "Nombre de edificio"
+
+#: src/components/form/InputLocation.tsx:42
+#, c-format
+msgid "Street"
+msgstr "Calle"
+
+#: src/components/form/InputLocation.tsx:43
+#, c-format
+msgid "Post code"
+msgstr "Código postal"
+
+#: src/components/form/InputLocation.tsx:44
+#, c-format
+msgid "Town location"
+msgstr "Ubicación de ciudad"
+
+#: src/components/form/InputLocation.tsx:45
+#, c-format
+msgid "Town"
+msgstr "Ciudad"
+
+#: src/components/form/InputLocation.tsx:46
+#, c-format
+msgid "District"
+msgstr "Distrito"
+
+#: src/components/form/InputLocation.tsx:49
+#, c-format
+msgid "Country subdivision"
+msgstr "Subdivisión de país"
+
+#: src/components/form/InputSearchProduct.tsx:66
+#, c-format
+msgid "Product id"
+msgstr "Id de producto"
+
+#: src/components/form/InputSearchProduct.tsx:69
+#, c-format
+msgid "Description"
+msgstr "Descripcion"
+
+#: src/components/form/InputSearchProduct.tsx:94
+#, fuzzy, c-format
+msgid "Product"
+msgstr "Productos"
+
+#: src/components/form/InputSearchProduct.tsx:95
+#, c-format
+msgid "search products by it's description or id"
+msgstr "buscar productos por su descripción o ID"
+
+#: src/components/form/InputSearchProduct.tsx:151
+#, c-format
+msgid "no products found with that description"
+msgstr "no se encontraron productos con esa descripción"
+
+#: src/components/product/InventoryProductForm.tsx:56
+#, c-format
+msgid "You must enter a valid product identifier."
+msgstr "Debe ingresar un identificador de producto válido."
+
+#: src/components/product/InventoryProductForm.tsx:64
+#, c-format
+msgid "Quantity must be greater than 0!"
+msgstr "¡Cantidad debe ser mayor que 0!"
+
+#: src/components/product/InventoryProductForm.tsx:76
+#, fuzzy, c-format
+msgid ""
+"This quantity exceeds remaining stock. Currently, only %1$s units remain "
+"unreserved in stock."
+msgstr ""
+"Esta cantidad excede las existencias restantes. Actualmente, solo quedan "
+"%1$s unidades sin reservar en las existencias."
+
+#: src/components/product/InventoryProductForm.tsx:109
+#, c-format
+msgid "Quantity"
+msgstr "Cantidad"
+
+#: src/components/product/InventoryProductForm.tsx:110
+#, c-format
+msgid "how many products will be added"
+msgstr "cuántos productos serán agregados"
+
+#: src/components/product/InventoryProductForm.tsx:117
+#, c-format
+msgid "Add from inventory"
+msgstr "Agregar del inventario"
+
+#: src/components/form/InputImage.tsx:105
+#, c-format
+msgid "Image should be smaller than 1 MB"
+msgstr "La imagen debe ser mas chica que 1 MB"
+
+#: src/components/form/InputImage.tsx:110
+#, c-format
+msgid "Add"
+msgstr "Agregar"
+
+#: src/components/form/InputImage.tsx:115
+#, c-format
+msgid "Remove"
+msgstr "Eliminar"
+
+#: src/components/form/InputTaxes.tsx:113
+#, c-format
+msgid "No taxes configured for this product."
+msgstr "Ningun impuesto configurado para este producto."
+
+#: src/components/form/InputTaxes.tsx:119
+#, c-format
+msgid "Amount"
+msgstr "Monto"
+
+#: src/components/form/InputTaxes.tsx:120
+#, c-format
+msgid ""
+"Taxes can be in currencies that differ from the main currency used by the "
+"merchant."
+msgstr ""
+"Impuestos pueden estar en divisas que difieren de la principal divisa usada "
+"por el comerciante."
+
+#: src/components/form/InputTaxes.tsx:122
+#, c-format
+msgid ""
+"Enter currency and value separated with a colon, e.g. &quot;USD:2.3&quot;."
+msgstr ""
+"Ingrese divisa y valor separado por dos puntos, e.g. &quot;USD:2.3&quot;."
+
+#: src/components/form/InputTaxes.tsx:131
+#, c-format
+msgid "Legal name of the tax, e.g. VAT or import duties."
+msgstr "Nombre legal del impuesto, e.g. IVA o arancel."
+
+#: src/components/form/InputTaxes.tsx:137
+#, c-format
+msgid "add tax to the tax list"
+msgstr "agregar impuesto a la lista de impuestos"
+
+#: src/components/product/NonInventoryProductForm.tsx:72
+#, c-format
+msgid "describe and add a product that is not in the inventory list"
+msgstr "describa y agregue un producto que no está en la lista de inventarios"
+
+#: src/components/product/NonInventoryProductForm.tsx:75
+#, c-format
+msgid "Add custom product"
+msgstr "Agregue un producto personalizado"
+
+#: src/components/product/NonInventoryProductForm.tsx:86
+#, c-format
+msgid "Complete information of the product"
+msgstr "Complete información del producto"
+
+#: src/components/product/NonInventoryProductForm.tsx:185
+#, c-format
+msgid "Image"
+msgstr "Imagen"
+
+#: src/components/product/NonInventoryProductForm.tsx:186
+#, c-format
+msgid "photo of the product"
+msgstr "foto del producto"
+
+#: src/components/product/NonInventoryProductForm.tsx:192
+#, c-format
+msgid "full product description"
+msgstr "descripción completa del producto"
+
+#: src/components/product/NonInventoryProductForm.tsx:196
+#, c-format
+msgid "Unit"
+msgstr "Unidad"
+
+#: src/components/product/NonInventoryProductForm.tsx:197
+#, c-format
+msgid "name of the product unit"
+msgstr "nombre de la unidad del producto"
+
+#: src/components/product/NonInventoryProductForm.tsx:201
+#, c-format
+msgid "Price"
+msgstr "Precio"
+
+#: src/components/product/NonInventoryProductForm.tsx:202
+#, c-format
+msgid "amount in the current currency"
+msgstr "monto de la divisa actual"
+
+#: src/components/product/NonInventoryProductForm.tsx:211
+#, c-format
+msgid "Taxes"
+msgstr "Impuestos"
+
+#: src/components/product/ProductList.tsx:38
+#, c-format
+msgid "image"
+msgstr "imagen"
+
+#: src/components/product/ProductList.tsx:41
+#, c-format
+msgid "description"
+msgstr "descripción"
+
+#: src/components/product/ProductList.tsx:44
+#, c-format
+msgid "quantity"
+msgstr "cantidad"
+
+#: src/components/product/ProductList.tsx:47
+#, c-format
+msgid "unit price"
+msgstr "precio unitario"
+
+#: src/components/product/ProductList.tsx:50
+#, c-format
+msgid "total price"
+msgstr "precio total"
+
+#: src/paths/instance/orders/create/CreatePage.tsx:153
+#, c-format
+msgid "required"
+msgstr "requerido"
+
+#: src/paths/instance/orders/create/CreatePage.tsx:157
+#, fuzzy, c-format
+msgid "not valid"
+msgstr "no es un json válido"
+
+#: src/paths/instance/orders/create/CreatePage.tsx:159
+#, c-format
+msgid "must be greater than 0"
+msgstr "debe ser mayor que 0"
+
+#: src/paths/instance/orders/create/CreatePage.tsx:164
+#, c-format
+msgid "not a valid json"
+msgstr "no es un json válido"
+
+#: src/paths/instance/orders/create/CreatePage.tsx:170
+#, c-format
+msgid "should be in the future"
+msgstr "deberían ser en el futuro"
+
+#: src/paths/instance/orders/create/CreatePage.tsx:173
+#, c-format
+msgid "refund deadline cannot be before pay deadline"
+msgstr "plazo de reembolso no puede ser antes que el plazo de pago"
+
+#: src/paths/instance/orders/create/CreatePage.tsx:179
+#, c-format
+msgid "wire transfer deadline cannot be before refund deadline"
+msgstr ""
+"el plazo de la transferencia bancaria no puede ser antes que el plazo de "
+"reembolso"
+
+#: src/paths/instance/orders/create/CreatePage.tsx:190
+#, c-format
+msgid "wire transfer deadline cannot be before pay deadline"
+msgstr ""
+"el plazo de la transferencia bancaria no puede ser antes que el plazo de pago"
+
+#: src/paths/instance/orders/create/CreatePage.tsx:197
+#, c-format
+msgid "should have a refund deadline"
+msgstr "debería tener un plazo de reembolso"
+
+#: src/paths/instance/orders/create/CreatePage.tsx:202
+#, c-format
+msgid "auto refund cannot be after refund deadline"
+msgstr "reembolso automático no puede ser después qu el plazo de reembolso"
+
+#: src/paths/instance/orders/create/CreatePage.tsx:360
+#, c-format
+msgid "Manage products in order"
+msgstr "Manejar productos en orden"
+
+#: src/paths/instance/orders/create/CreatePage.tsx:369
+#, c-format
+msgid "Manage list of products in the order."
+msgstr "Manejar lista de productos en la orden."
+
+#: src/paths/instance/orders/create/CreatePage.tsx:391
+#, c-format
+msgid "Remove this product from the order."
+msgstr "Remover este producto de la orden."
+
+#: src/paths/instance/orders/create/CreatePage.tsx:415
+#, c-format
+msgid "Total price"
+msgstr "Precio total"
+
+#: src/paths/instance/orders/create/CreatePage.tsx:417
+#, c-format
+msgid "total product price added up"
+msgstr "precio total de producto agregado"
+
+#: src/paths/instance/orders/create/CreatePage.tsx:430
+#, c-format
+msgid "Amount to be paid by the customer"
+msgstr "Monto a ser pagado por el cliente"
+
+#: src/paths/instance/orders/create/CreatePage.tsx:436
+#, c-format
+msgid "Order price"
+msgstr "Precio de la orden"
+
+#: src/paths/instance/orders/create/CreatePage.tsx:437
+#, c-format
+msgid "final order price"
+msgstr "Precio final de la orden"
+
+#: src/paths/instance/orders/create/CreatePage.tsx:444
+#, c-format
+msgid "Summary"
+msgstr "Resumen"
+
+#: src/paths/instance/orders/create/CreatePage.tsx:445
+#, c-format
+msgid "Title of the order to be shown to the customer"
+msgstr "Título de la orden a ser mostrado al cliente"
+
+#: src/paths/instance/orders/create/CreatePage.tsx:450
+#, c-format
+msgid "Shipping and Fulfillment"
+msgstr "Envío y cumplimiento"
+
+#: src/paths/instance/orders/create/CreatePage.tsx:455
+#, c-format
+msgid "Delivery date"
+msgstr "Fecha de entrega"
+
+#: src/paths/instance/orders/create/CreatePage.tsx:456
+#, c-format
+msgid "Deadline for physical delivery assured by the merchant."
+msgstr "Plazo para la entrega física asegurado por el comerciante."
+
+#: src/paths/instance/orders/create/CreatePage.tsx:461
+#, c-format
+msgid "Location"
+msgstr "Ubicación"
+
+#: src/paths/instance/orders/create/CreatePage.tsx:462
+#, c-format
+msgid "address where the products will be delivered"
+msgstr "dirección a donde los productos serán entregados"
+
+#: src/paths/instance/orders/create/CreatePage.tsx:469
+#, c-format
+msgid "Fulfillment URL"
+msgstr "URL de cumplimiento"
+
+#: src/paths/instance/orders/create/CreatePage.tsx:470
+#, c-format
+msgid "URL to which the user will be redirected after successful payment."
+msgstr "URL al cual el usuario será redirigido luego de pago exitoso."
+
+#: src/paths/instance/orders/create/CreatePage.tsx:476
+#, c-format
+msgid "Taler payment options"
+msgstr "Opciones de pago de Taler"
+
+#: src/paths/instance/orders/create/CreatePage.tsx:477
+#, c-format
+msgid "Override default Taler payment settings for this order"
+msgstr "Sobreescribir pagos por omisión de Taler para esta orden"
+
+#: src/paths/instance/orders/create/CreatePage.tsx:481
+#, fuzzy, c-format
+msgid "Payment deadline"
+msgstr "Plazo de pago"
+
+#: src/paths/instance/orders/create/CreatePage.tsx:482
+#, c-format
+msgid ""
+"Deadline for the customer to pay for the offer before it expires. Inventory "
+"products will be reserved until this deadline."
+msgstr ""
+"Plazo límite para que el cliente pague por la oferta antes de que expire. "
+"Productos del inventario serán reservados hasta este plazo límite."
+
+#: src/paths/instance/orders/create/CreatePage.tsx:486
+#, c-format
+msgid "Refund deadline"
+msgstr "Plazo de reembolso"
+
+#: src/paths/instance/orders/create/CreatePage.tsx:487
+#, c-format
+msgid "Time until which the order can be refunded by the merchant."
+msgstr ""
+"Tiempo hasta el cual la orden puede ser reembolsada por el comerciante."
+
+#: src/paths/instance/orders/create/CreatePage.tsx:491
+#, c-format
+msgid "Wire transfer deadline"
+msgstr "Plazo de la transferencia"
+
+#: src/paths/instance/orders/create/CreatePage.tsx:492
+#, c-format
+msgid "Deadline for the exchange to make the wire transfer."
+msgstr "Plazo para que el exchange haga la transferencia."
+
+#: src/paths/instance/orders/create/CreatePage.tsx:496
+#, fuzzy, c-format
+msgid "Auto-refund deadline"
+msgstr "Plazo de reembolso automático"
+
+#: src/paths/instance/orders/create/CreatePage.tsx:497
+#, c-format
+msgid ""
+"Time until which the wallet will automatically check for refunds without "
+"user interaction."
+msgstr ""
+"Tiempo hasta el cual la billetera será automáticamente revisada por "
+"reembolsos win interación por parte del usuario."
+
+#: src/paths/instance/orders/create/CreatePage.tsx:502
+#, c-format
+msgid "Maximum deposit fee"
+msgstr "Máxima tarifa de depósito"
+
+#: src/paths/instance/orders/create/CreatePage.tsx:503
+#, c-format
+msgid ""
+"Maximum deposit fees the merchant is willing to cover for this order. Higher "
+"deposit fees must be covered in full by the consumer."
+msgstr ""
+"Máxima tarifa de depósito que el comerciante esta dispuesto a cubir para "
+"esta orden. Mayores tarifas de depósito deben ser cubiertas completamente "
+"por el consumidor."
+
+#: src/paths/instance/orders/create/CreatePage.tsx:507
+#, c-format
+msgid "Maximum wire fee"
+msgstr "Máxima tarifa de transferencia"
+
+#: src/paths/instance/orders/create/CreatePage.tsx:508
+#, c-format
+msgid ""
+"Maximum aggregate wire fees the merchant is willing to cover for this order. "
+"Wire fees exceeding this amount are to be covered by the customers."
+msgstr ""
+
+#: src/paths/instance/orders/create/CreatePage.tsx:512
+#, c-format
+msgid "Wire fee amortization"
+msgstr "Amortización de comisión de transferencia"
+
+#: src/paths/instance/orders/create/CreatePage.tsx:513
+#, c-format
+msgid ""
+"Factor by which wire fees exceeding the above threshold are divided to "
+"determine the share of excess wire fees to be paid explicitly by the "
+"consumer."
+msgstr ""
+
+#: src/paths/instance/orders/create/CreatePage.tsx:517
+#, fuzzy, c-format
+msgid "Create token"
+msgstr "Administrar token"
+
+#: src/paths/instance/orders/create/CreatePage.tsx:518
+#, c-format
+msgid ""
+"Uncheck this option if the merchant backend generated an order ID with "
+"enough entropy to prevent adversarial claims."
+msgstr ""
+
+#: src/paths/instance/orders/create/CreatePage.tsx:522
+#, fuzzy, c-format
+msgid "Minimum age required"
+msgstr "Login necesario"
+
+#: src/paths/instance/orders/create/CreatePage.tsx:523
+#, c-format
+msgid ""
+"Any value greater than 0 will limit the coins able be used to pay this "
+"contract. If empty the age restriction will be defined by the products"
+msgstr ""
+
+#: src/paths/instance/orders/create/CreatePage.tsx:526
+#, c-format
+msgid "Min age defined by the producs is %1$s"
+msgstr ""
+
+#: src/paths/instance/orders/create/CreatePage.tsx:534
+#, fuzzy, c-format
+msgid "Additional information"
+msgstr "Información extra"
+
+#: src/paths/instance/orders/create/CreatePage.tsx:535
+#, c-format
+msgid "Custom information to be included in the contract for this order."
+msgstr ""
+
+#: src/paths/instance/orders/create/CreatePage.tsx:541
+#, c-format
+msgid "You must enter a value in JavaScript Object Notation (JSON)."
+msgstr ""
+
+#: src/components/picker/DurationPicker.tsx:55
+#, c-format
+msgid "days"
+msgstr "días"
+
+#: src/components/picker/DurationPicker.tsx:65
+#, c-format
+msgid "hours"
+msgstr "horas"
+
+#: src/components/picker/DurationPicker.tsx:76
+#, c-format
+msgid "minutes"
+msgstr "minutos"
+
+#: src/components/picker/DurationPicker.tsx:87
+#, c-format
+msgid "seconds"
+msgstr "segundos"
+
+#: src/components/form/InputDuration.tsx:53
+#, fuzzy, c-format
+msgid "forever"
+msgstr "nunca"
+
+#: src/components/form/InputDuration.tsx:62
+#, c-format
+msgid "%1$sM"
+msgstr ""
+
+#: src/components/form/InputDuration.tsx:64
+#, c-format
+msgid "%1$sY"
+msgstr ""
+
+#: src/components/form/InputDuration.tsx:66
+#, c-format
+msgid "%1$sd"
+msgstr ""
+
+#: src/components/form/InputDuration.tsx:68
+#, c-format
+msgid "%1$sh"
+msgstr ""
+
+#: src/components/form/InputDuration.tsx:70
+#, c-format
+msgid "%1$smin"
+msgstr ""
+
+#: src/components/form/InputDuration.tsx:72
+#, c-format
+msgid "%1$ssec"
+msgstr ""
+
+#: src/paths/instance/orders/list/Table.tsx:75
+#, c-format
+msgid "Orders"
+msgstr "Órdenes"
+
+#: src/paths/instance/orders/list/Table.tsx:81
+#, fuzzy, c-format
+msgid "create order"
+msgstr "creado"
+
+#: src/paths/instance/orders/list/Table.tsx:147
+#, c-format
+msgid "load newer orders"
+msgstr "cargar nuevas ordenes"
+
+#: src/paths/instance/orders/list/Table.tsx:154
+#, c-format
+msgid "Date"
+msgstr "Fecha"
+
+#: src/paths/instance/orders/list/Table.tsx:200
+#, c-format
+msgid "Refund"
+msgstr "Devolución"
+
+#: src/paths/instance/orders/list/Table.tsx:209
+#, c-format
+msgid "copy url"
+msgstr "copiar url"
+
+#: src/paths/instance/orders/list/Table.tsx:225
+#, c-format
+msgid "load older orders"
+msgstr "cargar viejas ordenes"
+
+#: src/paths/instance/orders/list/Table.tsx:242
+#, c-format
+msgid "No orders have been found matching your query!"
+msgstr "¡No se encontraron órdenes que emparejen su búsqueda!"
+
+#: src/paths/instance/orders/list/Table.tsx:288
+#, c-format
+msgid "duplicated"
+msgstr "duplicado"
+
+#: src/paths/instance/orders/list/Table.tsx:299
+#, c-format
+msgid "invalid format"
+msgstr "formato inválido"
+
+#: src/paths/instance/orders/list/Table.tsx:301
+#, c-format
+msgid "this value exceed the refundable amount"
+msgstr "este monto excede el monto reembolsable"
+
+#: src/paths/instance/orders/list/Table.tsx:346
+#, c-format
+msgid "date"
+msgstr "fecha"
+
+#: src/paths/instance/orders/list/Table.tsx:349
+#, c-format
+msgid "amount"
+msgstr "monto"
+
+#: src/paths/instance/orders/list/Table.tsx:352
+#, c-format
+msgid "reason"
+msgstr "razón"
+
+#: src/paths/instance/orders/list/Table.tsx:389
+#, c-format
+msgid "amount to be refunded"
+msgstr "monto a ser reembolsado"
+
+#: src/paths/instance/orders/list/Table.tsx:391
+#, c-format
+msgid "Max refundable:"
+msgstr "Máximo reembolzable:"
+
+#: src/paths/instance/orders/list/Table.tsx:396
+#, c-format
+msgid "Reason"
+msgstr "Razón"
+
+#: src/paths/instance/orders/list/Table.tsx:397
+#, c-format
+msgid "Choose one..."
+msgstr "Elija uno..."
+
+#: src/paths/instance/orders/list/Table.tsx:399
+#, c-format
+msgid "requested by the customer"
+msgstr "pedido por el consumidor"
+
+#: src/paths/instance/orders/list/Table.tsx:400
+#, c-format
+msgid "other"
+msgstr "otro"
+
+#: src/paths/instance/orders/list/Table.tsx:403
+#, c-format
+msgid "why this order is being refunded"
+msgstr "por qué esta orden está siendo reembolsada"
+
+#: src/paths/instance/orders/list/Table.tsx:409
+#, c-format
+msgid "more information to give context"
+msgstr "más información para dar contexto"
+
+#: src/paths/instance/orders/details/DetailPage.tsx:62
+#, c-format
+msgid "Contract Terms"
+msgstr "Términos de contrato"
+
+#: src/paths/instance/orders/details/DetailPage.tsx:68
+#, c-format
+msgid "human-readable description of the whole purchase"
+msgstr "descripción legible de toda la compra"
+
+#: src/paths/instance/orders/details/DetailPage.tsx:74
+#, c-format
+msgid "total price for the transaction"
+msgstr "precio total de la transacción"
+
+#: src/paths/instance/orders/details/DetailPage.tsx:81
+#, c-format
+msgid "URL for this purchase"
+msgstr "URL para esta compra"
+
+#: src/paths/instance/orders/details/DetailPage.tsx:87
+#, c-format
+msgid "Max fee"
+msgstr "Máxima comisión"
+
+#: src/paths/instance/orders/details/DetailPage.tsx:88
+#, c-format
+msgid "maximum total deposit fee accepted by the merchant for this contract"
+msgstr ""
+
+#: src/paths/instance/orders/details/DetailPage.tsx:93
+#, c-format
+msgid "Max wire fee"
+msgstr "Impuesto de transferencia máximo"
+
+#: src/paths/instance/orders/details/DetailPage.tsx:94
+#, c-format
+msgid "maximum wire fee accepted by the merchant"
+msgstr ""
+
+#: src/paths/instance/orders/details/DetailPage.tsx:100
+#, c-format
+msgid ""
+"over how many customer transactions does the merchant expect to amortize "
+"wire fees on average"
+msgstr ""
+
+#: src/paths/instance/orders/details/DetailPage.tsx:105
+#, c-format
+msgid "Created at"
+msgstr "Creado en"
+
+#: src/paths/instance/orders/details/DetailPage.tsx:106
+#, c-format
+msgid "time when this contract was generated"
+msgstr ""
+
+#: src/paths/instance/orders/details/DetailPage.tsx:112
+#, c-format
+msgid "after this deadline has passed no refunds will be accepted"
+msgstr ""
+
+#: src/paths/instance/orders/details/DetailPage.tsx:118
+#, c-format
+msgid ""
+"after this deadline, the merchant won't accept payments for the contract"
+msgstr ""
+
+#: src/paths/instance/orders/details/DetailPage.tsx:124
+#, c-format
+msgid "transfer deadline for the exchange"
+msgstr ""
+
+#: src/paths/instance/orders/details/DetailPage.tsx:130
+#, c-format
+msgid "time indicating when the order should be delivered"
+msgstr ""
+
+#: src/paths/instance/orders/details/DetailPage.tsx:136
+#, c-format
+msgid "where the order will be delivered"
+msgstr ""
+
+#: src/paths/instance/orders/details/DetailPage.tsx:144
+#, fuzzy, c-format
+msgid "Auto-refund delay"
+msgstr "Plazo de reembolso automático"
+
+#: src/paths/instance/orders/details/DetailPage.tsx:145
+#, c-format
+msgid ""
+"how long the wallet should try to get an automatic refund for the purchase"
+msgstr ""
+
+#: src/paths/instance/orders/details/DetailPage.tsx:150
+#, fuzzy, c-format
+msgid "Extra info"
+msgstr "Información extra"
+
+#: src/paths/instance/orders/details/DetailPage.tsx:151
+#, c-format
+msgid "extra data that is only interpreted by the merchant frontend"
+msgstr ""
+
+#: src/paths/instance/orders/details/DetailPage.tsx:219
+#, c-format
+msgid "Order"
+msgstr "Orden"
+
+#: src/paths/instance/orders/details/DetailPage.tsx:221
+#, c-format
+msgid "claimed"
+msgstr "reclamado"
+
+#: src/paths/instance/orders/details/DetailPage.tsx:247
+#, fuzzy, c-format
+msgid "claimed at"
+msgstr "reclamado"
+
+#: src/paths/instance/orders/details/DetailPage.tsx:265
+#, c-format
+msgid "Timeline"
+msgstr "Cronología"
+
+#: src/paths/instance/orders/details/DetailPage.tsx:271
+#, c-format
+msgid "Payment details"
+msgstr "Detalles de pago"
+
+#: src/paths/instance/orders/details/DetailPage.tsx:291
+#, c-format
+msgid "Order status"
+msgstr "Estado de orden"
+
+#: src/paths/instance/orders/details/DetailPage.tsx:301
+#, c-format
+msgid "Product list"
+msgstr "Lista de producto"
+
+#: src/paths/instance/orders/details/DetailPage.tsx:451
+#, c-format
+msgid "paid"
+msgstr "pagados"
+
+#: src/paths/instance/orders/details/DetailPage.tsx:455
+#, c-format
+msgid "wired"
+msgstr "transferido"
+
+#: src/paths/instance/orders/details/DetailPage.tsx:460
+#, c-format
+msgid "refunded"
+msgstr "reembolzado"
+
+#: src/paths/instance/orders/details/DetailPage.tsx:480
+#, fuzzy, c-format
+msgid "refund order"
+msgstr "reembolzado"
+
+#: src/paths/instance/orders/details/DetailPage.tsx:481
+#, fuzzy, c-format
+msgid "not refundable"
+msgstr "Máximo reembolzable:"
+
+#: src/paths/instance/orders/details/DetailPage.tsx:489
+#, c-format
+msgid "refund"
+msgstr "reembolzar"
+
+#: src/paths/instance/orders/details/DetailPage.tsx:553
+#, c-format
+msgid "Refunded amount"
+msgstr "Monto reembolzado"
+
+#: src/paths/instance/orders/details/DetailPage.tsx:560
+#, fuzzy, c-format
+msgid "Refund taken"
+msgstr "Reembolzado"
+
+#: src/paths/instance/orders/details/DetailPage.tsx:570
+#, fuzzy, c-format
+msgid "Status URL"
+msgstr "URL de estado de orden"
+
+#: src/paths/instance/orders/details/DetailPage.tsx:583
+#, fuzzy, c-format
+msgid "Refund URI"
+msgstr "Devolución"
+
+#: src/paths/instance/orders/details/DetailPage.tsx:636
+#, c-format
+msgid "unpaid"
+msgstr "impago"
+
+#: src/paths/instance/orders/details/DetailPage.tsx:654
+#, c-format
+msgid "pay at"
+msgstr "pagar en"
+
+#: src/paths/instance/orders/details/DetailPage.tsx:666
+#, c-format
+msgid "created at"
+msgstr "creado"
+
+#: src/paths/instance/orders/details/DetailPage.tsx:707
+#, c-format
+msgid "Order status URL"
+msgstr "URL de estado de orden"
+
+#: src/paths/instance/orders/details/DetailPage.tsx:711
+#, fuzzy, c-format
+msgid "Payment URI"
+msgstr "URI de pago"
+
+#: src/paths/instance/orders/details/DetailPage.tsx:740
+#, c-format
+msgid ""
+"Unknown order status. This is an error, please contact the administrator."
+msgstr ""
+"Estado de orden desconocido. Esto es un error, por favor contacte a su "
+"administrador."
+
+#: src/paths/instance/orders/details/DetailPage.tsx:767
+#, c-format
+msgid "Back"
+msgstr ""
+
+#: src/paths/instance/orders/details/index.tsx:79
+#, c-format
+msgid "refund created successfully"
+msgstr "reembolzo creado satisfactoriamente"
+
+#: src/paths/instance/orders/details/index.tsx:85
+#, c-format
+msgid "could not create the refund"
+msgstr "No se pudo create el reembolso"
+
+#: src/paths/instance/orders/list/ListPage.tsx:78
+#, c-format
+msgid "select date to show nearby orders"
+msgstr ""
+
+#: src/paths/instance/orders/list/ListPage.tsx:94
+#, fuzzy, c-format
+msgid "order id"
+msgstr "ir a id de orden"
+
+#: src/paths/instance/orders/list/ListPage.tsx:100
+#, c-format
+msgid "jump to order with the given order ID"
+msgstr ""
+
+#: src/paths/instance/orders/list/ListPage.tsx:122
+#, c-format
+msgid "remove all filters"
+msgstr ""
+
+#: src/paths/instance/orders/list/ListPage.tsx:132
+#, c-format
+msgid "only show paid orders"
+msgstr ""
+
+#: src/paths/instance/orders/list/ListPage.tsx:135
+#, c-format
+msgid "Paid"
+msgstr "Pagado"
+
+#: src/paths/instance/orders/list/ListPage.tsx:142
+#, fuzzy, c-format
+msgid "only show orders with refunds"
+msgstr "No se pudo create el reembolso"
+
+#: src/paths/instance/orders/list/ListPage.tsx:145
+#, c-format
+msgid "Refunded"
+msgstr "Reembolsado"
+
+#: src/paths/instance/orders/list/ListPage.tsx:152
+#, c-format
+msgid ""
+"only show orders where customers paid, but wire payments from payment "
+"provider are still pending"
+msgstr ""
+
+#: src/paths/instance/orders/list/ListPage.tsx:155
+#, c-format
+msgid "Not wired"
+msgstr "No transferido"
+
+#: src/paths/instance/orders/list/ListPage.tsx:170
+#, c-format
+msgid "clear date filter"
+msgstr ""
+
+#: src/paths/instance/orders/list/ListPage.tsx:184
+#, c-format
+msgid "date (YYYY/MM/DD)"
+msgstr ""
+
+#: src/paths/instance/orders/list/index.tsx:103
+#, fuzzy, c-format
+msgid "Enter an order id"
+msgstr "ir a id de orden"
+
+#: src/paths/instance/orders/list/index.tsx:111
+#, fuzzy, c-format
+msgid "order not found"
+msgstr "Servidor no encontrado"
+
+#: src/paths/instance/orders/list/index.tsx:178
+#, fuzzy, c-format
+msgid "could not get the order to refund"
+msgstr "No se pudo create el reembolso"
+
+#: src/components/exception/AsyncButton.tsx:43
+#, fuzzy, c-format
+msgid "Loading..."
+msgstr "Cargando..."
+
+#: src/components/form/InputStock.tsx:99
+#, c-format
+msgid ""
+"click here to configure the stock of the product, leave it as is and the "
+"backend will not control stock"
+msgstr ""
+
+#: src/components/form/InputStock.tsx:109
+#, c-format
+msgid "Manage stock"
+msgstr "Administrar stock"
+
+#: src/components/form/InputStock.tsx:115
+#, c-format
+msgid "this product has been configured without stock control"
+msgstr ""
+
+#: src/components/form/InputStock.tsx:119
+#, c-format
+msgid "Infinite"
+msgstr "Inifinito"
+
+#: src/components/form/InputStock.tsx:136
+#, fuzzy, c-format
+msgid "lost cannot be greater than current and incoming (max %1$s)"
+msgstr "la pérdida no puede ser mayor al stock actual + entrante (max %1$s )"
+
+#: src/components/form/InputStock.tsx:176
+#, c-format
+msgid "Incoming"
+msgstr "Ingresando"
+
+#: src/components/form/InputStock.tsx:177
+#, c-format
+msgid "Lost"
+msgstr "Perdido"
+
+#: src/components/form/InputStock.tsx:192
+#, c-format
+msgid "Current"
+msgstr "Actual"
+
+#: src/components/form/InputStock.tsx:196
+#, c-format
+msgid "remove stock control for this product"
+msgstr ""
+
+#: src/components/form/InputStock.tsx:202
+#, c-format
+msgid "without stock"
+msgstr "sin stock"
+
+#: src/components/form/InputStock.tsx:211
+#, c-format
+msgid "Next restock"
+msgstr "Próximo reabastecimiento"
+
+#: src/components/form/InputStock.tsx:217
+#, c-format
+msgid "Delivery address"
+msgstr "Dirección de entrega"
+
+#: src/components/product/ProductForm.tsx:133
+#, c-format
+msgid "product identification to use in URLs (for internal use only)"
+msgstr ""
+
+#: src/components/product/ProductForm.tsx:139
+#, c-format
+msgid "illustration of the product for customers"
+msgstr ""
+
+#: src/components/product/ProductForm.tsx:145
+#, c-format
+msgid "product description for customers"
+msgstr ""
+
+#: src/components/product/ProductForm.tsx:149
+#, c-format
+msgid "Age restricted"
+msgstr ""
+
+#: src/components/product/ProductForm.tsx:150
+#, c-format
+msgid "is this product restricted for customer below certain age?"
+msgstr ""
+
+#: src/components/product/ProductForm.tsx:155
+#, c-format
+msgid ""
+"unit describing quantity of product sold (e.g. 2 kilograms, 5 liters, 3 "
+"items, 5 meters) for customers"
+msgstr ""
+
+#: src/components/product/ProductForm.tsx:160
+#, c-format
+msgid ""
+"sale price for customers, including taxes, for above units of the product"
+msgstr ""
+
+#: src/components/product/ProductForm.tsx:164
+#, c-format
+msgid "Stock"
+msgstr "Existencias"
+
+#: src/components/product/ProductForm.tsx:166
+#, c-format
+msgid ""
+"product inventory for products with finite supply (for internal use only)"
+msgstr ""
+
+#: src/components/product/ProductForm.tsx:171
+#, c-format
+msgid "taxes included in the product price, exposed to customers"
+msgstr ""
+
+#: src/paths/instance/products/create/CreatePage.tsx:66
+#, c-format
+msgid "Need to complete marked fields"
+msgstr ""
+
+#: src/paths/instance/products/create/index.tsx:51
+#, c-format
+msgid "could not create product"
+msgstr "no se pudo crear el producto"
+
+#: src/paths/instance/products/list/Table.tsx:68
+#, c-format
+msgid "Products"
+msgstr "Productos"
+
+#: src/paths/instance/products/list/Table.tsx:73
+#, c-format
+msgid "add product to inventory"
+msgstr ""
+
+#: src/paths/instance/products/list/Table.tsx:137
+#, c-format
+msgid "Sell"
+msgstr "Venta"
+
+#: src/paths/instance/products/list/Table.tsx:143
+#, c-format
+msgid "Profit"
+msgstr "Ganancia"
+
+#: src/paths/instance/products/list/Table.tsx:149
+#, c-format
+msgid "Sold"
+msgstr "Vendido"
+
+#: src/paths/instance/products/list/Table.tsx:210
+#, c-format
+msgid "free"
+msgstr "Gratis"
+
+#: src/paths/instance/products/list/Table.tsx:248
+#, fuzzy, c-format
+msgid "go to product update page"
+msgstr "producto actualizado correctamente"
+
+#: src/paths/instance/products/list/Table.tsx:255
+#, c-format
+msgid "Update"
+msgstr "Actualizar"
+
+#: src/paths/instance/products/list/Table.tsx:260
+#, c-format
+msgid "remove this product from the database"
+msgstr ""
+
+#: src/paths/instance/products/list/Table.tsx:331
+#, c-format
+msgid "update the product with new price"
+msgstr ""
+
+#: src/paths/instance/products/list/Table.tsx:341
+#, c-format
+msgid "update product with new price"
+msgstr ""
+
+#: src/paths/instance/products/list/Table.tsx:399
+#, c-format
+msgid "add more elements to the inventory"
+msgstr ""
+
+#: src/paths/instance/products/list/Table.tsx:404
+#, c-format
+msgid "report elements lost in the inventory"
+msgstr ""
+
+#: src/paths/instance/products/list/Table.tsx:409
+#, fuzzy, c-format
+msgid "new price for the product"
+msgstr "no se pudo actualizar el producto"
+
+#: src/paths/instance/products/list/Table.tsx:421
+#, c-format
+msgid "the are value with errors"
+msgstr ""
+
+#: src/paths/instance/products/list/Table.tsx:422
+#, c-format
+msgid "update product with new stock and price"
+msgstr ""
+
+#: src/paths/instance/products/list/Table.tsx:463
+#, fuzzy, c-format
+msgid "There is no products yet, add more pressing the + sign"
+msgstr "No hay propinas todavía, agregar mas presionando el signo +"
+
+#: src/paths/instance/products/list/index.tsx:86
+#, c-format
+msgid "product updated successfully"
+msgstr "producto actualizado correctamente"
+
+#: src/paths/instance/products/list/index.tsx:92
+#, c-format
+msgid "could not update the product"
+msgstr "no se pudo actualizar el producto"
+
+#: src/paths/instance/products/list/index.tsx:103
+#, c-format
+msgid "product delete successfully"
+msgstr "producto fue eliminado correctamente"
+
+#: src/paths/instance/products/list/index.tsx:109
+#, c-format
+msgid "could not delete the product"
+msgstr "no se pudo eliminar el producto"
+
+#: src/paths/instance/products/update/UpdatePage.tsx:56
+#, fuzzy, c-format
+msgid "Product id:"
+msgstr "Id de producto"
+
+#: src/paths/instance/reserves/create/CreatedSuccessfully.tsx:95
+#, c-format
+msgid ""
+"To complete the setup of the reserve, you must now initiate a wire transfer "
+"using the given wire transfer subject and crediting the specified amount to "
+"the indicated account of the exchange."
+msgstr ""
+
+#: src/paths/instance/reserves/create/CreatedSuccessfully.tsx:102
+#, c-format
+msgid "If your system supports RFC 8905, you can do this by opening this URI:"
+msgstr ""
+
+#: src/paths/instance/reserves/create/CreatePage.tsx:83
+#, fuzzy, c-format
+msgid "it should be greater than 0"
+msgstr "Debe ser mayor a 0"
+
+#: src/paths/instance/reserves/create/CreatePage.tsx:88
+#, c-format
+msgid "must be a valid URL"
+msgstr ""
+
+#: src/paths/instance/reserves/create/CreatePage.tsx:107
+#, fuzzy, c-format
+msgid "Initial balance"
+msgstr "Instancia"
+
+#: src/paths/instance/reserves/create/CreatePage.tsx:108
+#, c-format
+msgid "balance prior to deposit"
+msgstr ""
+
+#: src/paths/instance/reserves/create/CreatePage.tsx:112
+#, c-format
+msgid "Exchange URL"
+msgstr "URL del Exchange"
+
+#: src/paths/instance/reserves/create/CreatePage.tsx:113
+#, c-format
+msgid "URL of exchange"
+msgstr ""
+
+#: src/paths/instance/reserves/create/CreatePage.tsx:148
+#, c-format
+msgid "Next"
+msgstr "Siguiente"
+
+#: src/paths/instance/reserves/create/CreatePage.tsx:186
+#, c-format
+msgid "Wire method"
+msgstr ""
+
+#: src/paths/instance/reserves/create/CreatePage.tsx:187
+#, fuzzy, c-format
+msgid "method to use for wire transfer"
+msgstr "no se pudo informar la transferencia"
+
+#: src/paths/instance/reserves/create/CreatePage.tsx:189
+#, c-format
+msgid "Select one wire method"
+msgstr ""
+
+#: src/paths/instance/reserves/create/index.tsx:62
+#, fuzzy, c-format
+msgid "could not create reserve"
+msgstr "No se pudo create el reembolso"
+
+#: src/paths/instance/reserves/details/DetailPage.tsx:77
+#, c-format
+msgid "Valid until"
+msgstr "Válido hasta"
+
+#: src/paths/instance/reserves/details/DetailPage.tsx:82
+#, fuzzy, c-format
+msgid "Created balance"
+msgstr "creado"
+
+#: src/paths/instance/reserves/details/DetailPage.tsx:99
+#, fuzzy, c-format
+msgid "Exchange balance"
+msgstr "Monto inicial"
+
+#: src/paths/instance/reserves/details/DetailPage.tsx:104
+#, c-format
+msgid "Picked up"
+msgstr ""
+
+#: src/paths/instance/reserves/details/DetailPage.tsx:109
+#, fuzzy, c-format
+msgid "Committed"
+msgstr "Monto confirmado"
+
+#: src/paths/instance/reserves/details/DetailPage.tsx:116
+#, c-format
+msgid "Account address"
+msgstr "Dirección de cuenta"
+
+#: src/paths/instance/reserves/details/DetailPage.tsx:119
+#, c-format
+msgid "Subject"
+msgstr "Asunto"
+
+#: src/paths/instance/reserves/details/DetailPage.tsx:130
+#, c-format
+msgid "Tips"
+msgstr "Propinas"
+
+#: src/paths/instance/reserves/details/DetailPage.tsx:193
+#, c-format
+msgid "No tips has been authorized from this reserve"
+msgstr ""
+
+#: src/paths/instance/reserves/details/DetailPage.tsx:213
+#, fuzzy, c-format
+msgid "Authorized"
+msgstr "Token de autorización"
+
+#: src/paths/instance/reserves/details/DetailPage.tsx:222
+#, fuzzy, c-format
+msgid "Expiration"
+msgstr "Información extra"
+
+#: src/paths/instance/reserves/list/AutorizeTipModal.tsx:108
+#, fuzzy, c-format
+msgid "amount of tip"
+msgstr "monto"
+
+#: src/paths/instance/reserves/list/AutorizeTipModal.tsx:112
+#, fuzzy, c-format
+msgid "Justification"
+msgstr "Jurisdicción"
+
+#: src/paths/instance/reserves/list/AutorizeTipModal.tsx:114
+#, c-format
+msgid "reason for the tip"
+msgstr ""
+
+#: src/paths/instance/reserves/list/AutorizeTipModal.tsx:118
+#, c-format
+msgid "URL after tip"
+msgstr ""
+
+#: src/paths/instance/reserves/list/AutorizeTipModal.tsx:119
+#, c-format
+msgid "URL to visit after tip payment"
+msgstr ""
+
+#: src/paths/instance/reserves/list/Table.tsx:65
+#, fuzzy, c-format
+msgid "Reserves not yet funded"
+msgstr "Servidor no encontrado"
+
+#: src/paths/instance/reserves/list/Table.tsx:89
+#, c-format
+msgid "Reserves ready"
+msgstr ""
+
+#: src/paths/instance/reserves/list/Table.tsx:95
+#, fuzzy, c-format
+msgid "add new reserve"
+msgstr "cargar nuevas transferencias"
+
+#: src/paths/instance/reserves/list/Table.tsx:143
+#, c-format
+msgid "Expires at"
+msgstr ""
+
+#: src/paths/instance/reserves/list/Table.tsx:146
+#, c-format
+msgid "Initial"
+msgstr ""
+
+#: src/paths/instance/reserves/list/Table.tsx:202
+#, c-format
+msgid "delete selected reserve from the database"
+msgstr ""
+
+#: src/paths/instance/reserves/list/Table.tsx:210
+#, c-format
+msgid "authorize new tip from selected reserve"
+msgstr ""
+
+#: src/paths/instance/reserves/list/Table.tsx:237
+#, fuzzy, c-format
+msgid ""
+"There is no ready reserves yet, add more pressing the + sign or fund them"
+msgstr "No hay transferencias todavía, agregar mas presionando el signo +"
+
+#: src/paths/instance/reserves/list/Table.tsx:264
+#, fuzzy, c-format
+msgid "Expected Balance"
+msgstr "Ejecutado en"
+
+#: src/paths/instance/reserves/list/index.tsx:110
+#, fuzzy, c-format
+msgid "could not create the tip"
+msgstr "No se pudo create el reembolso"
+
+#: src/paths/instance/templates/create/CreatePage.tsx:77
+#, fuzzy, c-format
+msgid "should not be empty"
+msgstr "no puede ser vacío"
+
+#: src/paths/instance/templates/create/CreatePage.tsx:93
+#, fuzzy, c-format
+msgid "should be greater that 0"
+msgstr "Debe ser mayor a 0"
+
+#: src/paths/instance/templates/create/CreatePage.tsx:96
+#, fuzzy, c-format
+msgid "can't be empty"
+msgstr "no puede ser vacío"
+
+#: src/paths/instance/templates/create/CreatePage.tsx:100
+#, c-format
+msgid "to short"
+msgstr ""
+
+#: src/paths/instance/templates/create/CreatePage.tsx:108
+#, c-format
+msgid "just letters and numbers from 2 to 7"
+msgstr ""
+
+#: src/paths/instance/templates/create/CreatePage.tsx:110
+#, c-format
+msgid "size of the key should be 32"
+msgstr ""
+
+#: src/paths/instance/templates/create/CreatePage.tsx:137
+#, c-format
+msgid "Identifier"
+msgstr ""
+
+#: src/paths/instance/templates/create/CreatePage.tsx:138
+#, c-format
+msgid "Name of the template in URLs."
+msgstr ""
+
+#: src/paths/instance/templates/create/CreatePage.tsx:144
+#, c-format
+msgid "Describe what this template stands for"
+msgstr ""
+
+#: src/paths/instance/templates/create/CreatePage.tsx:149
+#, fuzzy, c-format
+msgid "Fixed summary"
+msgstr "Estado de orden"
+
+#: src/paths/instance/templates/create/CreatePage.tsx:150
+#, c-format
+msgid "If specified, this template will create order with the same summary"
+msgstr ""
+
+#: src/paths/instance/templates/create/CreatePage.tsx:154
+#, fuzzy, c-format
+msgid "Fixed price"
+msgstr "precio unitario"
+
+#: src/paths/instance/templates/create/CreatePage.tsx:155
+#, c-format
+msgid "If specified, this template will create order with the same price"
+msgstr ""
+
+#: src/paths/instance/templates/create/CreatePage.tsx:159
+#, c-format
+msgid "Minimum age"
+msgstr "Edad mínima"
+
+#: src/paths/instance/templates/create/CreatePage.tsx:161
+#, c-format
+msgid "Is this contract restricted to some age?"
+msgstr ""
+
+#: src/paths/instance/templates/create/CreatePage.tsx:165
+#, fuzzy, c-format
+msgid "Payment timeout"
+msgstr "Opciones de pago"
+
+#: src/paths/instance/templates/create/CreatePage.tsx:167
+#, c-format
+msgid ""
+"How much time has the customer to complete the payment once the order was "
+"created."
+msgstr ""
+
+#: src/paths/instance/templates/create/CreatePage.tsx:171
+#, c-format
+msgid "Verification algorithm"
+msgstr ""
+
+#: src/paths/instance/templates/create/CreatePage.tsx:172
+#, c-format
+msgid "Algorithm to use to verify transaction in offline mode"
+msgstr ""
+
+#: src/paths/instance/templates/create/CreatePage.tsx:180
+#, c-format
+msgid "Point-of-sale key"
+msgstr ""
+
+#: src/paths/instance/templates/create/CreatePage.tsx:182
+#, c-format
+msgid "Useful to validate the purchase"
+msgstr ""
+
+#: src/paths/instance/templates/create/CreatePage.tsx:196
+#, c-format
+msgid "generate random secret key"
+msgstr ""
+
+#: src/paths/instance/templates/create/CreatePage.tsx:203
+#, c-format
+msgid "random"
+msgstr ""
+
+#: src/paths/instance/templates/create/CreatePage.tsx:208
+#, c-format
+msgid "show secret key"
+msgstr ""
+
+#: src/paths/instance/templates/create/CreatePage.tsx:209
+#, c-format
+msgid "hide secret key"
+msgstr ""
+
+#: src/paths/instance/templates/create/CreatePage.tsx:216
+#, c-format
+msgid "hide"
+msgstr ""
+
+#: src/paths/instance/templates/create/CreatePage.tsx:218
+#, c-format
+msgid "show"
+msgstr ""
+
+#: src/paths/instance/templates/create/index.tsx:52
+#, fuzzy, c-format
+msgid "could not inform template"
+msgstr "no se pudo informar la transferencia"
+
+#: src/paths/instance/templates/use/UsePage.tsx:54
+#, fuzzy, c-format
+msgid "Amount is required"
+msgstr "Login necesario"
+
+#: src/paths/instance/templates/use/UsePage.tsx:58
+#, c-format
+msgid "Order summary is required"
+msgstr ""
+
+#: src/paths/instance/templates/use/UsePage.tsx:86
+#, fuzzy, c-format
+msgid "New order for template"
+msgstr "cargar viejas transferencias"
+
+#: src/paths/instance/templates/use/UsePage.tsx:108
+#, c-format
+msgid "Amount of the order"
+msgstr ""
+
+#: src/paths/instance/templates/use/UsePage.tsx:113
+#, fuzzy, c-format
+msgid "Order summary"
+msgstr "Estado de orden"
+
+#: src/paths/instance/templates/use/index.tsx:92
+#, fuzzy, c-format
+msgid "could not create order from template"
+msgstr "No se pudo create el reembolso"
+
+#: src/paths/instance/templates/qr/QrPage.tsx:131
+#, c-format
+msgid ""
+"Here you can specify a default value for fields that are not fixed. Default "
+"values can be edited by the customer before the payment."
+msgstr ""
+
+#: src/paths/instance/templates/qr/QrPage.tsx:148
+#, fuzzy, c-format
+msgid "Fixed amount"
+msgstr "Monto reembolzado"
+
+#: src/paths/instance/templates/qr/QrPage.tsx:149
+#, fuzzy, c-format
+msgid "Default amount"
+msgstr "Monto reembolzado"
+
+#: src/paths/instance/templates/qr/QrPage.tsx:161
+#, fuzzy, c-format
+msgid "Default summary"
+msgstr "Estado de orden"
+
+#: src/paths/instance/templates/qr/QrPage.tsx:177
+#, c-format
+msgid "Print"
+msgstr ""
+
+#: src/paths/instance/templates/qr/QrPage.tsx:184
+#, c-format
+msgid "Setup TOTP"
+msgstr ""
+
+#: src/paths/instance/templates/list/Table.tsx:65
+#, c-format
+msgid "Templates"
+msgstr ""
+
+#: src/paths/instance/templates/list/Table.tsx:70
+#, c-format
+msgid "add new templates"
+msgstr ""
+
+#: src/paths/instance/templates/list/Table.tsx:142
+#, c-format
+msgid "load more templates before the first one"
+msgstr ""
+
+#: src/paths/instance/templates/list/Table.tsx:146
+#, fuzzy, c-format
+msgid "load newer templates"
+msgstr "cargar nuevas transferencias"
+
+#: src/paths/instance/templates/list/Table.tsx:181
+#, c-format
+msgid "delete selected templates from the database"
+msgstr ""
+
+#: src/paths/instance/templates/list/Table.tsx:188
+#, c-format
+msgid "use template to create new order"
+msgstr ""
+
+#: src/paths/instance/templates/list/Table.tsx:195
+#, fuzzy, c-format
+msgid "create qr code for the template"
+msgstr "No se pudo create el reembolso"
+
+#: src/paths/instance/templates/list/Table.tsx:210
+#, c-format
+msgid "load more templates after the last one"
+msgstr ""
+
+#: src/paths/instance/templates/list/Table.tsx:214
+#, fuzzy, c-format
+msgid "load older templates"
+msgstr "cargar viejas transferencias"
+
+#: src/paths/instance/templates/list/Table.tsx:231
+#, fuzzy, c-format
+msgid "There is no templates yet, add more pressing the + sign"
+msgstr "No hay propinas todavía, agregar mas presionando el signo +"
+
+#: src/paths/instance/templates/list/index.tsx:104
+#, fuzzy, c-format
+msgid "template delete successfully"
+msgstr "producto fue eliminado correctamente"
+
+#: src/paths/instance/templates/list/index.tsx:110
+#, fuzzy, c-format
+msgid "could not delete the template"
+msgstr "no se pudo eliminar el producto"
+
+#: src/paths/instance/templates/update/index.tsx:90
+#, fuzzy, c-format
+msgid "could not update template"
+msgstr "no se pudo actualizar el producto"
+
+#: src/paths/instance/webhooks/create/CreatePage.tsx:57
+#, fuzzy, c-format
+msgid "should be one of '%1$s'"
+msgstr "deberían ser iguales"
+
+#: src/paths/instance/webhooks/create/CreatePage.tsx:85
+#, c-format
+msgid "Webhook ID to use"
+msgstr ""
+
+#: src/paths/instance/webhooks/create/CreatePage.tsx:89
+#, c-format
+msgid "Event"
+msgstr ""
+
+#: src/paths/instance/webhooks/create/CreatePage.tsx:90
+#, c-format
+msgid "The event of the webhook: why the webhook is used"
+msgstr ""
+
+#: src/paths/instance/webhooks/create/CreatePage.tsx:94
+#, c-format
+msgid "Method"
+msgstr ""
+
+#: src/paths/instance/webhooks/create/CreatePage.tsx:95
+#, c-format
+msgid "Method used by the webhook"
+msgstr ""
+
+#: src/paths/instance/webhooks/create/CreatePage.tsx:99
+#, c-format
+msgid "URL"
+msgstr "URL"
+
+#: src/paths/instance/webhooks/create/CreatePage.tsx:100
+#, c-format
+msgid "URL of the webhook where the customer will be redirected"
+msgstr ""
+
+#: src/paths/instance/webhooks/create/CreatePage.tsx:104
+#, c-format
+msgid "Header"
+msgstr ""
+
+#: src/paths/instance/webhooks/create/CreatePage.tsx:106
+#, c-format
+msgid "Header template of the webhook"
+msgstr ""
+
+#: src/paths/instance/webhooks/create/CreatePage.tsx:111
+#, c-format
+msgid "Body"
+msgstr ""
+
+#: src/paths/instance/webhooks/create/CreatePage.tsx:112
+#, c-format
+msgid "Body template by the webhook"
+msgstr ""
+
+#: src/paths/instance/webhooks/list/Table.tsx:61
+#, c-format
+msgid "Webhooks"
+msgstr ""
+
+#: src/paths/instance/webhooks/list/Table.tsx:66
+#, c-format
+msgid "add new webhooks"
+msgstr ""
+
+#: src/paths/instance/webhooks/list/Table.tsx:137
+#, c-format
+msgid "load more webhooks before the first one"
+msgstr ""
+
+#: src/paths/instance/webhooks/list/Table.tsx:141
+#, fuzzy, c-format
+msgid "load newer webhooks"
+msgstr "cargar nuevas ordenes"
+
+#: src/paths/instance/webhooks/list/Table.tsx:151
+#, c-format
+msgid "Event type"
+msgstr ""
+
+#: src/paths/instance/webhooks/list/Table.tsx:176
+#, c-format
+msgid "delete selected webhook from the database"
+msgstr ""
+
+#: src/paths/instance/webhooks/list/Table.tsx:198
+#, c-format
+msgid "load more webhooks after the last one"
+msgstr ""
+
+#: src/paths/instance/webhooks/list/Table.tsx:202
+#, fuzzy, c-format
+msgid "load older webhooks"
+msgstr "cargar viejas ordenes"
+
+#: src/paths/instance/webhooks/list/Table.tsx:219
+#, fuzzy, c-format
+msgid "There is no webhooks yet, add more pressing the + sign"
+msgstr "No hay propinas todavía, agregar mas presionando el signo +"
+
+#: src/paths/instance/webhooks/list/index.tsx:94
+#, fuzzy, c-format
+msgid "webhook delete successfully"
+msgstr "producto fue eliminado correctamente"
+
+#: src/paths/instance/webhooks/list/index.tsx:100
+#, fuzzy, c-format
+msgid "could not delete the webhook"
+msgstr "no se pudo eliminar el producto"
+
+#: src/paths/instance/transfers/create/CreatePage.tsx:63
+#, fuzzy, c-format
+msgid "check the id, does not look valid"
+msgstr "verificar el id, no parece válido"
+
+#: src/paths/instance/transfers/create/CreatePage.tsx:65
+#, c-format
+msgid "should have 52 characters, current %1$s"
+msgstr "debería tener 52 caracteres, actualmente %1$s"
+
+#: src/paths/instance/transfers/create/CreatePage.tsx:72
+#, c-format
+msgid "URL doesn't have the right format"
+msgstr "La URL no tiene el formato correcto"
+
+#: src/paths/instance/transfers/create/CreatePage.tsx:98
+#, c-format
+msgid "Credited bank account"
+msgstr ""
+
+#: src/paths/instance/transfers/create/CreatePage.tsx:100
+#, c-format
+msgid "Select one account"
+msgstr ""
+
+#: src/paths/instance/transfers/create/CreatePage.tsx:101
+#, c-format
+msgid "Bank account of the merchant where the payment was received"
+msgstr ""
+
+#: src/paths/instance/transfers/create/CreatePage.tsx:105
+#, fuzzy, c-format
+msgid "Wire transfer ID"
+msgstr "Id de transferencia"
+
+#: src/paths/instance/transfers/create/CreatePage.tsx:107
+#, c-format
+msgid ""
+"unique identifier of the wire transfer used by the exchange, must be 52 "
+"characters long"
+msgstr ""
+
+#: src/paths/instance/transfers/create/CreatePage.tsx:112
+#, c-format
+msgid ""
+"Base URL of the exchange that made the transfer, should have been in the "
+"wire transfer subject"
+msgstr ""
+
+#: src/paths/instance/transfers/create/CreatePage.tsx:117
+#, c-format
+msgid "Amount credited"
+msgstr ""
+
+#: src/paths/instance/transfers/create/CreatePage.tsx:118
+#, c-format
+msgid "Actual amount that was wired to the merchant's bank account"
+msgstr ""
+
+#: src/paths/instance/transfers/create/index.tsx:58
+#, c-format
+msgid "could not inform transfer"
+msgstr "no se pudo informar la transferencia"
+
+#: src/paths/instance/transfers/list/Table.tsx:61
+#, c-format
+msgid "Transfers"
+msgstr "Transferencias"
+
+#: src/paths/instance/transfers/list/Table.tsx:66
+#, fuzzy, c-format
+msgid "add new transfer"
+msgstr "cargar nuevas transferencias"
+
+#: src/paths/instance/transfers/list/Table.tsx:129
+#, c-format
+msgid "load more transfers before the first one"
+msgstr ""
+
+#: src/paths/instance/transfers/list/Table.tsx:133
+#, c-format
+msgid "load newer transfers"
+msgstr "cargar nuevas transferencias"
+
+#: src/paths/instance/transfers/list/Table.tsx:143
+#, c-format
+msgid "Credit"
+msgstr "Crédito"
+
+#: src/paths/instance/transfers/list/Table.tsx:152
+#, c-format
+msgid "Confirmed"
+msgstr "Confirmado"
+
+#: src/paths/instance/transfers/list/Table.tsx:155
+#, c-format
+msgid "Verified"
+msgstr "Verificado"
+
+#: src/paths/instance/transfers/list/Table.tsx:158
+#, c-format
+msgid "Executed at"
+msgstr "Ejecutado en"
+
+#: src/paths/instance/transfers/list/Table.tsx:171
+#, c-format
+msgid "yes"
+msgstr "si"
+
+#: src/paths/instance/transfers/list/Table.tsx:171
+#, c-format
+msgid "no"
+msgstr "no"
+
+#: src/paths/instance/transfers/list/Table.tsx:181
+#, c-format
+msgid "unknown"
+msgstr "desconocido"
+
+#: src/paths/instance/transfers/list/Table.tsx:187
+#, c-format
+msgid "delete selected transfer from the database"
+msgstr "eliminar transferencia seleccionada de la base de datos"
+
+#: src/paths/instance/transfers/list/Table.tsx:202
+#, c-format
+msgid "load more transfer after the last one"
+msgstr "cargue más transferencia luego de la última"
+
+#: src/paths/instance/transfers/list/Table.tsx:206
+#, c-format
+msgid "load older transfers"
+msgstr "cargar viejas transferencias"
+
+#: src/paths/instance/transfers/list/Table.tsx:223
+#, c-format
+msgid "There is no transfer yet, add more pressing the + sign"
+msgstr "No hay transferencias todavía, agregar mas presionando el signo +"
+
+#: src/paths/instance/transfers/list/ListPage.tsx:79
+#, fuzzy, c-format
+msgid "filter by account address"
+msgstr "Dirección de cuenta"
+
+#: src/paths/instance/transfers/list/ListPage.tsx:100
+#, c-format
+msgid "only show wire transfers confirmed by the merchant"
+msgstr ""
+
+#: src/paths/instance/transfers/list/ListPage.tsx:110
+#, c-format
+msgid "only show wire transfers claimed by the exchange"
+msgstr ""
+
+#: src/paths/instance/transfers/list/ListPage.tsx:113
+#, fuzzy, c-format
+msgid "Unverified"
+msgstr "Verificado"
+
+#: src/paths/admin/create/CreatePage.tsx:69
+#, c-format
+msgid "is not valid"
+msgstr ""
+
+#: src/paths/admin/create/CreatePage.tsx:94
+#, fuzzy, c-format
+msgid "is not a number"
+msgstr "Número de edificio"
+
+#: src/paths/admin/create/CreatePage.tsx:96
+#, c-format
+msgid "must be 1 or greater"
+msgstr "debe ser 1 o mayor"
+
+#: src/paths/admin/create/CreatePage.tsx:107
+#, c-format
+msgid "max 7 lines"
+msgstr "máximo 7 líneas"
+
+#: src/paths/admin/create/CreatePage.tsx:178
+#, c-format
+msgid "change authorization configuration"
+msgstr "cambiar configuración de autorización"
+
+#: src/paths/admin/create/CreatePage.tsx:217
+#, c-format
+msgid "Need to complete marked fields and choose authorization method"
+msgstr "Necesita completar campos marcados y escoger un método de autorización"
+
+#: src/components/form/InputPaytoForm.tsx:82
+#, c-format
+msgid "This is not a valid bitcoin address."
+msgstr "Esta no es una dirección de bitcoin válida."
+
+#: src/components/form/InputPaytoForm.tsx:95
+#, c-format
+msgid "This is not a valid Ethereum address."
+msgstr "Esta no es una dirección de Ethereum válida."
+
+#: src/components/form/InputPaytoForm.tsx:118
+#, c-format
+msgid "IBAN numbers usually have more that 4 digits"
+msgstr "Números IBAN usualmente tienen más de 4 dígitos"
+
+#: src/components/form/InputPaytoForm.tsx:120
+#, c-format
+msgid "IBAN numbers usually have less that 34 digits"
+msgstr "Número IBAN usualmente tienen menos de 34 dígitos"
+
+#: src/components/form/InputPaytoForm.tsx:128
+#, c-format
+msgid "IBAN country code not found"
+msgstr "Código IBAN de país no encontrado"
+
+#: src/components/form/InputPaytoForm.tsx:153
+#, c-format
+msgid "IBAN number is not valid, checksum is wrong"
+msgstr "Número IBAN no es válido, la suma de verificación es incorrecta"
+
+#: src/components/form/InputPaytoForm.tsx:248
+#, c-format
+msgid "Target type"
+msgstr "Tipo objetivo"
+
+#: src/components/form/InputPaytoForm.tsx:249
+#, c-format
+msgid "Method to use for wire transfer"
+msgstr "Método a usar para la transferencia"
+
+#: src/components/form/InputPaytoForm.tsx:258
+#, c-format
+msgid "Routing"
+msgstr "Enrutamiento"
+
+#: src/components/form/InputPaytoForm.tsx:259
+#, c-format
+msgid "Routing number."
+msgstr "Número de enrutamiento."
+
+#: src/components/form/InputPaytoForm.tsx:263
+#, c-format
+msgid "Account"
+msgstr "Cuenta"
+
+#: src/components/form/InputPaytoForm.tsx:264
+#, fuzzy, c-format
+msgid "Account number."
+msgstr "Dirección de cuenta"
+
+#: src/components/form/InputPaytoForm.tsx:273
+#, c-format
+msgid "Business Identifier Code."
+msgstr ""
+
+#: src/components/form/InputPaytoForm.tsx:282
+#, c-format
+msgid "Bank Account Number."
+msgstr ""
+
+#: src/components/form/InputPaytoForm.tsx:292
+#, c-format
+msgid "Unified Payment Interface."
+msgstr "Interfaz de pago unificado."
+
+#: src/components/form/InputPaytoForm.tsx:301
+#, c-format
+msgid "Bitcoin protocol."
+msgstr ""
+
+#: src/components/form/InputPaytoForm.tsx:310
+#, c-format
+msgid "Ethereum protocol."
+msgstr ""
+
+#: src/components/form/InputPaytoForm.tsx:319
+#, c-format
+msgid "Interledger protocol."
+msgstr ""
+
+#: src/components/form/InputPaytoForm.tsx:328
+#, c-format
+msgid "Host"
+msgstr ""
+
+#: src/components/form/InputPaytoForm.tsx:329
+#, c-format
+msgid "Bank host."
+msgstr ""
+
+#: src/components/form/InputPaytoForm.tsx:334
+#, c-format
+msgid "Bank account."
+msgstr ""
+
+#: src/components/form/InputPaytoForm.tsx:343
+#, c-format
+msgid "Bank account owner's name."
+msgstr ""
+
+#: src/components/form/InputPaytoForm.tsx:370
+#, c-format
+msgid "No accounts yet."
+msgstr ""
+
+#: src/components/instance/DefaultInstanceFormFields.tsx:52
+#, c-format
+msgid ""
+"Name of the instance in URLs. The 'default' instance is special in that it "
+"is used to administer other instances."
+msgstr ""
+
+#: src/components/instance/DefaultInstanceFormFields.tsx:58
+#, fuzzy, c-format
+msgid "Business name"
+msgstr "Nombre de edificio"
+
+#: src/components/instance/DefaultInstanceFormFields.tsx:59
+#, c-format
+msgid "Legal name of the business represented by this instance."
+msgstr ""
+
+#: src/components/instance/DefaultInstanceFormFields.tsx:64
+#, c-format
+msgid "Email"
+msgstr ""
+
+#: src/components/instance/DefaultInstanceFormFields.tsx:65
+#, c-format
+msgid "Contact email"
+msgstr ""
+
+#: src/components/instance/DefaultInstanceFormFields.tsx:70
+#, c-format
+msgid "Website URL"
+msgstr "URL de sitio web"
+
+#: src/components/instance/DefaultInstanceFormFields.tsx:71
+#, c-format
+msgid "URL."
+msgstr ""
+
+#: src/components/instance/DefaultInstanceFormFields.tsx:76
+#, c-format
+msgid "Logo"
+msgstr ""
+
+#: src/components/instance/DefaultInstanceFormFields.tsx:77
+#, c-format
+msgid "Logo image."
+msgstr ""
+
+#: src/components/instance/DefaultInstanceFormFields.tsx:82
+#, c-format
+msgid "Bank account"
+msgstr "Cuenta bancaria"
+
+#: src/components/instance/DefaultInstanceFormFields.tsx:83
+#, c-format
+msgid "URI specifying bank account for crediting revenue."
+msgstr ""
+
+#: src/components/instance/DefaultInstanceFormFields.tsx:88
+#, c-format
+msgid "Default max deposit fee"
+msgstr "Impuesto máximo de deposito por omisión"
+
+#: src/components/instance/DefaultInstanceFormFields.tsx:89
+#, c-format
+msgid ""
+"Maximum deposit fees this merchant is willing to pay per order by default."
+msgstr ""
+
+#: src/components/instance/DefaultInstanceFormFields.tsx:94
+#, c-format
+msgid "Default max wire fee"
+msgstr "Impuesto máximo de transferencia por omisión"
+
+#: src/components/instance/DefaultInstanceFormFields.tsx:95
+#, c-format
+msgid ""
+"Maximum wire fees this merchant is willing to pay per wire transfer by "
+"default."
+msgstr ""
+
+#: src/components/instance/DefaultInstanceFormFields.tsx:100
+#, c-format
+msgid "Default wire fee amortization"
+msgstr "Amortización de impuesto de transferencia por omisión"
+
+#: src/components/instance/DefaultInstanceFormFields.tsx:101
+#, c-format
+msgid ""
+"Number of orders excess wire transfer fees will be divided by to compute per "
+"order surcharge."
+msgstr ""
+
+#: src/components/instance/DefaultInstanceFormFields.tsx:107
+#, c-format
+msgid "Physical location of the merchant."
+msgstr ""
+
+#: src/components/instance/DefaultInstanceFormFields.tsx:114
+#, c-format
+msgid "Jurisdiction"
+msgstr "Jurisdicción"
+
+#: src/components/instance/DefaultInstanceFormFields.tsx:115
+#, c-format
+msgid "Jurisdiction for legal disputes with the merchant."
+msgstr "Jurisdicción para disputas legales con el comerciante."
+
+#: src/components/instance/DefaultInstanceFormFields.tsx:122
+#, fuzzy, c-format
+msgid "Default payment delay"
+msgstr "Retrazo de pago por omisión"
+
+#: src/components/instance/DefaultInstanceFormFields.tsx:124
+#, c-format
+msgid ""
+"Time customers have to pay an order before the offer expires by default."
+msgstr ""
+
+#: src/components/instance/DefaultInstanceFormFields.tsx:129
+#, c-format
+msgid "Default wire transfer delay"
+msgstr "Retrazo de transferencia por omisión"
+
+#: src/components/instance/DefaultInstanceFormFields.tsx:130
+#, c-format
+msgid ""
+"Maximum time an exchange is allowed to delay wiring funds to the merchant, "
+"enabling it to aggregate smaller payments into larger wire transfers and "
+"reducing wire fees."
+msgstr ""
+
+#: src/paths/instance/update/UpdatePage.tsx:164
+#, c-format
+msgid "Instance id"
+msgstr "ID de instancia"
+
+#: src/paths/instance/update/UpdatePage.tsx:173
+#, fuzzy, c-format
+msgid "Change the authorization method use for this instance."
+msgstr ""
+"Limpiar el token de autorización significa acceso público a la instancia"
+
+#: src/paths/instance/update/UpdatePage.tsx:182
+#, c-format
+msgid "Manage access token"
+msgstr "Administrar token de acceso"
+
+#: src/paths/instance/update/index.tsx:112
+#, c-format
+msgid "Failed to create instance"
+msgstr "Fallo al crear la instancia"
+
+#: src/components/exception/login.tsx:74
+#, c-format
+msgid "Login required"
+msgstr "Login necesario"
+
+#: src/components/exception/login.tsx:80
+#, c-format
+msgid "Please enter your access token."
+msgstr ""
+
+#: src/components/exception/login.tsx:108
+#, fuzzy, c-format
+msgid "Access Token"
+msgstr "Acceso denegado"
+
+#: src/InstanceRoutes.tsx:171
+#, c-format
+msgid "The request to the backend take too long and was cancelled"
+msgstr ""
+
+#: src/InstanceRoutes.tsx:172
+#, c-format
+msgid "Diagnostic from %1$s is \"%2$s\""
+msgstr ""
+
+#: src/InstanceRoutes.tsx:178
+#, fuzzy, c-format
+msgid "The backend reported a problem: HTTP status #%1$s"
+msgstr "Servidir reporto un problema: HTTP status #%1$s"
+
+#: src/InstanceRoutes.tsx:179
+#, c-format
+msgid "Diagnostic from %1$s is '%2$s'"
+msgstr ""
+
+#: src/InstanceRoutes.tsx:196
+#, c-format
+msgid "Access denied"
+msgstr "Acceso denegado"
+
+#: src/InstanceRoutes.tsx:197
+#, c-format
+msgid "The access token provided is invalid."
+msgstr ""
+
+#: src/InstanceRoutes.tsx:212
+#, fuzzy, c-format
+msgid "No 'default' instance configured yet."
+msgstr "Sin instancia default"
+
+#: src/InstanceRoutes.tsx:213
+#, c-format
+msgid "Create a 'default' instance to begin using the merchant backoffice."
+msgstr ""
+
+#: src/InstanceRoutes.tsx:630
+#, c-format
+msgid "The access token provided is invalid"
+msgstr ""
+
+#: src/InstanceRoutes.tsx:664
+#, c-format
+msgid "Hide for today"
+msgstr ""
+
+#: src/components/menu/SideBar.tsx:82
+#, c-format
+msgid "Instance"
+msgstr "Instancia"
+
+#: src/components/menu/SideBar.tsx:91
+#, c-format
+msgid "Settings"
+msgstr "Configuración"
+
+#: src/components/menu/SideBar.tsx:167
+#, c-format
+msgid "Connection"
+msgstr "Conexión"
+
+#: src/components/menu/SideBar.tsx:209
+#, c-format
+msgid "New"
+msgstr "Nuevo"
+
+#: src/components/menu/SideBar.tsx:219
+#, c-format
+msgid "List"
+msgstr "Lista"
+
+#: src/components/menu/SideBar.tsx:234
+#, c-format
+msgid "Log out"
+msgstr "Salir"
+
+#: src/ApplicationReadyRoutes.tsx:71
+#, c-format
+msgid "Check your token is valid"
+msgstr "Verifica que el token sea valido"
+
+#: src/ApplicationReadyRoutes.tsx:90
+#, c-format
+msgid "Couldn't access the server."
+msgstr "No se pudo acceder al servidor."
+
+#: src/ApplicationReadyRoutes.tsx:91
+#, c-format
+msgid "Could not infer instance id from url %1$s"
+msgstr "No se pudo inferir el id de la instancia con la url %1$s"
+
+#: src/Application.tsx:104
+#, c-format
+msgid "Server not found"
+msgstr "Servidor no encontrado"
+
+#: src/Application.tsx:118
+#, c-format
+msgid "Server response with an error code"
+msgstr ""
+
+#: src/Application.tsx:120
+#, c-format
+msgid "Got message %1$s from %2$s"
+msgstr "Recibimos el mensaje %1$s desde %2$s"
+
+#: src/Application.tsx:131
+#, c-format
+msgid "Response from server is unreadable, http status: %1$s"
+msgstr ""
+
+#: src/Application.tsx:144
+#, c-format
+msgid "Unexpected Error"
+msgstr "Error inesperado"
+
+#: src/components/form/InputArray.tsx:101
+#, c-format
+msgid "The value %1$s is invalid for a payment url"
+msgstr "El valor %1$s es invalido para una URL de pago"
+
+#: src/components/form/InputArray.tsx:110
+#, c-format
+msgid "add element to the list"
+msgstr "agregar elemento a la lista"
+
+#: src/components/form/InputArray.tsx:112
+#, c-format
+msgid "add"
+msgstr "Agregar"
+
+#: src/components/form/InputSecured.tsx:37
+#, c-format
+msgid "Deleting"
+msgstr "Borrando"
+
+#: src/components/form/InputSecured.tsx:41
+#, c-format
+msgid "Changing"
+msgstr "Cambiando"
+
+#: src/paths/instance/orders/create/OrderCreatedSuccessfully.tsx:87
+#, c-format
+msgid "Order ID"
+msgstr "ID de pedido"
+
+#: src/paths/instance/orders/create/OrderCreatedSuccessfully.tsx:101
+#, c-format
+msgid "Payment URL"
+msgstr "URL de pago"
+
+#, c-format
+#~ msgid "Couldn't access the server"
+#~ msgstr "No se pudo aceder al servidor"
+
+#, c-format
+#~ msgid "HTTP status #%1$s: Server reported a problem"
+#~ msgstr "HTTP status #%1$s: Servidor reporto un problema"
+
+#, c-format
+#~ msgid "Got message: \"%1$s\" from: %2$s"
+#~ msgstr "Recibimos el mensaje: %1$s desde %2$s"
+
+#, c-format
+#~ msgid ""
+#~ "in order to use merchant backoffice, you should create the default "
+#~ "instance"
+#~ msgstr ""
+#~ "para usar el merchant backoffice, debería crear la instancia default"
+
+#, c-format
+#~ msgid "Got message: %1$s from: %2$s"
+#~ msgstr "Recibimos el mensaje %1$s desde %2$s"
+
+#, c-format
+#~ msgid ""
+#~ "Please enter your auth token. Token should have \"secret-token:\" and "
+#~ "start with Bearer or ApiKey"
+#~ msgstr ""
+#~ "Por favor ingrese su token de autorización. El token debe tener \"secret-"
+#~ "token\" y comenzar con Bearer o ApiKey"
+
+#, c-format
+#~ msgid "pick a date"
+#~ msgstr "elegir una fecha"
+
+#, c-format
+#~ msgid "no results"
+#~ msgstr "Sin resultados"
+
+#, c-format
+#~ msgid "current stock will change from %1$s to %2$s"
+#~ msgstr "stock actual cambiará desde %1$s a %2$s"
+
+#, c-format
+#~ msgid "current stock will stay at %1$s"
+#~ msgstr "stock actual seguirá en %1$s"
+
+#, c-format
+#~ msgid "this product has no taxes"
+#~ msgstr "este producto no tiene impuestos"
+
+#, c-format
+#~ msgid "Inventory products"
+#~ msgstr "Productos de inventario"
+
+#, c-format
+#~ msgid "Total tax"
+#~ msgstr "Impuesto total"
+
+#, c-format
+#~ msgid "Net"
+#~ msgstr "Neto"
+
+#, c-format
+#~ msgid "select a product first"
+#~ msgstr "seleccione un producto primero"
+
+#, c-format
+#~ msgid ""
+#~ "cannot be greater than current stock and quantity previously added. max: "
+#~ "%1$s"
+#~ msgstr ""
+#~ "no puede ser mayor al stock actual y la cantidad previamente agregada. "
+#~ "máximo: %1$s"
+
+#, c-format
+#~ msgid "cannot be greater than current stock %1$s"
+#~ msgstr "no puede ser mayor al stock actual %1$s"
+
+#, c-format
+#~ msgid "Deposit total"
+#~ msgstr "Total depositado"
+
+#, c-format
+#~ msgid "Merchant initial amount"
+#~ msgstr "Monto inicial"
+
+#, c-format
+#~ msgid "Account Address"
+#~ msgstr "Dirección de cuenta"
diff --git a/packages/auditor-backoffice-ui/src/i18n/fr.po 
b/packages/auditor-backoffice-ui/src/i18n/fr.po
new file mode 100644
index 000000000..d8d0bae29
--- /dev/null
+++ b/packages/auditor-backoffice-ui/src/i18n/fr.po
@@ -0,0 +1,2741 @@
+# This file is part of TALER
+# (C) 2016 GNUnet e.V.
+#
+# TALER is free software; you can redistribute it and/or modify it under the
+# terms of the GNU General Public License as published by the Free Software
+# Foundation; either version 3, or (at your option) any later version.
+#
+# TALER is distributed in the hope that it will be useful, but WITHOUT ANY
+# WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
+# A PARTICULAR PURPOSE.  See the GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License along with
+# TALER; see the file COPYING.  If not, see <http://www.gnu.org/licenses/>
+#
+#, fuzzy
+msgid ""
+msgstr ""
+"Project-Id-Version: Taler Wallet\n"
+"Report-Msgid-Bugs-To: taler@gnu.org\n"
+"POT-Creation-Date: 2016-11-23 00:00+0100\n"
+"PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n"
+"Last-Translator: FULL NAME <EMAIL@ADDRESS>\n"
+"Language-Team: LANGUAGE <LL@li.org>\n"
+"Language: \n"
+"MIME-Version: 1.0\n"
+"Content-Type: text/plain; charset=UTF-8\n"
+"Content-Transfer-Encoding: 8bit\n"
+"Plural-Forms: nplurals=2; plural=(n != 1);\n"
+
+#: src/components/modal/index.tsx:71
+#, c-format
+msgid "Cancel"
+msgstr ""
+
+#: src/components/modal/index.tsx:79
+#, c-format
+msgid "%1$s"
+msgstr ""
+
+#: src/components/modal/index.tsx:84
+#, c-format
+msgid "Close"
+msgstr ""
+
+#: src/components/modal/index.tsx:124
+#, c-format
+msgid "Continue"
+msgstr ""
+
+#: src/components/modal/index.tsx:178
+#, c-format
+msgid "Clear"
+msgstr ""
+
+#: src/components/modal/index.tsx:190
+#, c-format
+msgid "Confirm"
+msgstr ""
+
+#: src/components/modal/index.tsx:296
+#, c-format
+msgid "is not the same as the current access token"
+msgstr ""
+
+#: src/components/modal/index.tsx:299
+#, c-format
+msgid "cannot be empty"
+msgstr ""
+
+#: src/components/modal/index.tsx:301
+#, c-format
+msgid "cannot be the same as the old token"
+msgstr ""
+
+#: src/components/modal/index.tsx:305
+#, c-format
+msgid "is not the same"
+msgstr ""
+
+#: src/components/modal/index.tsx:315
+#, c-format
+msgid "You are updating the access token from instance with id %1$s"
+msgstr ""
+
+#: src/components/modal/index.tsx:331
+#, c-format
+msgid "Old access token"
+msgstr ""
+
+#: src/components/modal/index.tsx:332
+#, c-format
+msgid "access token currently in use"
+msgstr ""
+
+#: src/components/modal/index.tsx:338
+#, c-format
+msgid "New access token"
+msgstr ""
+
+#: src/components/modal/index.tsx:339
+#, c-format
+msgid "next access token to be used"
+msgstr ""
+
+#: src/components/modal/index.tsx:344
+#, c-format
+msgid "Repeat access token"
+msgstr ""
+
+#: src/components/modal/index.tsx:345
+#, c-format
+msgid "confirm the same access token"
+msgstr ""
+
+#: src/components/modal/index.tsx:350
+#, c-format
+msgid "Clearing the access token will mean public access to the instance"
+msgstr ""
+
+#: src/components/modal/index.tsx:377
+#, c-format
+msgid "cannot be the same as the old access token"
+msgstr ""
+
+#: src/components/modal/index.tsx:394
+#, c-format
+msgid "You are setting the access token for the new instance"
+msgstr ""
+
+#: src/components/modal/index.tsx:420
+#, c-format
+msgid ""
+"With external authorization method no check will be done by the merchant "
+"backend"
+msgstr ""
+
+#: src/components/modal/index.tsx:436
+#, c-format
+msgid "Set external authorization"
+msgstr ""
+
+#: src/components/modal/index.tsx:448
+#, c-format
+msgid "Set access token"
+msgstr ""
+
+#: src/components/modal/index.tsx:470
+#, c-format
+msgid "Operation in progress..."
+msgstr ""
+
+#: src/components/modal/index.tsx:479
+#, c-format
+msgid "The operation will be automatically canceled after %1$s seconds"
+msgstr ""
+
+#: src/paths/admin/list/TableActive.tsx:80
+#, c-format
+msgid "Instances"
+msgstr ""
+
+#: src/paths/admin/list/TableActive.tsx:93
+#, c-format
+msgid "Delete"
+msgstr ""
+
+#: src/paths/admin/list/TableActive.tsx:99
+#, c-format
+msgid "add new instance"
+msgstr ""
+
+#: src/paths/admin/list/TableActive.tsx:178
+#, c-format
+msgid "ID"
+msgstr ""
+
+#: src/paths/admin/list/TableActive.tsx:181
+#, c-format
+msgid "Name"
+msgstr ""
+
+#: src/paths/admin/list/TableActive.tsx:220
+#, c-format
+msgid "Edit"
+msgstr ""
+
+#: src/paths/admin/list/TableActive.tsx:237
+#, c-format
+msgid "Purge"
+msgstr ""
+
+#: src/paths/admin/list/TableActive.tsx:261
+#, c-format
+msgid "There is no instances yet, add more pressing the + sign"
+msgstr ""
+
+#: src/paths/admin/list/View.tsx:68
+#, c-format
+msgid "Only show active instances"
+msgstr ""
+
+#: src/paths/admin/list/View.tsx:71
+#, c-format
+msgid "Active"
+msgstr ""
+
+#: src/paths/admin/list/View.tsx:78
+#, c-format
+msgid "Only show deleted instances"
+msgstr ""
+
+#: src/paths/admin/list/View.tsx:81
+#, c-format
+msgid "Deleted"
+msgstr ""
+
+#: src/paths/admin/list/View.tsx:88
+#, c-format
+msgid "Show all instances"
+msgstr ""
+
+#: src/paths/admin/list/View.tsx:91
+#, c-format
+msgid "All"
+msgstr ""
+
+#: src/paths/admin/list/index.tsx:101
+#, c-format
+msgid "Instance \"%1$s\" (ID: %2$s) has been deleted"
+msgstr ""
+
+#: src/paths/admin/list/index.tsx:106
+#, c-format
+msgid "Failed to delete instance"
+msgstr ""
+
+#: src/paths/admin/list/index.tsx:124
+#, c-format
+msgid "Instance '%1$s' (ID: %2$s) has been disabled"
+msgstr ""
+
+#: src/paths/admin/list/index.tsx:129
+#, c-format
+msgid "Failed to purge instance"
+msgstr ""
+
+#: src/paths/instance/kyc/list/ListPage.tsx:41
+#, c-format
+msgid "Pending KYC verification"
+msgstr ""
+
+#: src/paths/instance/kyc/list/ListPage.tsx:66
+#, c-format
+msgid "Timed out"
+msgstr ""
+
+#: src/paths/instance/kyc/list/ListPage.tsx:103
+#, c-format
+msgid "Exchange"
+msgstr ""
+
+#: src/paths/instance/kyc/list/ListPage.tsx:106
+#, c-format
+msgid "Target account"
+msgstr ""
+
+#: src/paths/instance/kyc/list/ListPage.tsx:109
+#, c-format
+msgid "KYC URL"
+msgstr ""
+
+#: src/paths/instance/kyc/list/ListPage.tsx:144
+#, c-format
+msgid "Code"
+msgstr ""
+
+#: src/paths/instance/kyc/list/ListPage.tsx:147
+#, c-format
+msgid "Http Status"
+msgstr ""
+
+#: src/paths/instance/kyc/list/ListPage.tsx:177
+#, c-format
+msgid "No pending kyc verification!"
+msgstr ""
+
+#: src/components/form/InputDate.tsx:123
+#, c-format
+msgid "change value to unknown date"
+msgstr ""
+
+#: src/components/form/InputDate.tsx:124
+#, c-format
+msgid "change value to empty"
+msgstr ""
+
+#: src/components/form/InputDate.tsx:131
+#, c-format
+msgid "clear"
+msgstr ""
+
+#: src/components/form/InputDate.tsx:136
+#, c-format
+msgid "change value to never"
+msgstr ""
+
+#: src/components/form/InputDate.tsx:141
+#, c-format
+msgid "never"
+msgstr ""
+
+#: src/components/form/InputLocation.tsx:29
+#, c-format
+msgid "Country"
+msgstr ""
+
+#: src/components/form/InputLocation.tsx:33
+#, c-format
+msgid "Address"
+msgstr ""
+
+#: src/components/form/InputLocation.tsx:39
+#, c-format
+msgid "Building number"
+msgstr ""
+
+#: src/components/form/InputLocation.tsx:41
+#, c-format
+msgid "Building name"
+msgstr ""
+
+#: src/components/form/InputLocation.tsx:42
+#, c-format
+msgid "Street"
+msgstr ""
+
+#: src/components/form/InputLocation.tsx:43
+#, c-format
+msgid "Post code"
+msgstr ""
+
+#: src/components/form/InputLocation.tsx:44
+#, c-format
+msgid "Town location"
+msgstr ""
+
+#: src/components/form/InputLocation.tsx:45
+#, c-format
+msgid "Town"
+msgstr ""
+
+#: src/components/form/InputLocation.tsx:46
+#, c-format
+msgid "District"
+msgstr ""
+
+#: src/components/form/InputLocation.tsx:49
+#, c-format
+msgid "Country subdivision"
+msgstr ""
+
+#: src/components/form/InputSearchProduct.tsx:66
+#, c-format
+msgid "Product id"
+msgstr ""
+
+#: src/components/form/InputSearchProduct.tsx:69
+#, c-format
+msgid "Description"
+msgstr ""
+
+#: src/components/form/InputSearchProduct.tsx:94
+#, c-format
+msgid "Product"
+msgstr ""
+
+#: src/components/form/InputSearchProduct.tsx:95
+#, c-format
+msgid "search products by it's description or id"
+msgstr ""
+
+#: src/components/form/InputSearchProduct.tsx:151
+#, c-format
+msgid "no products found with that description"
+msgstr ""
+
+#: src/components/product/InventoryProductForm.tsx:56
+#, c-format
+msgid "You must enter a valid product identifier."
+msgstr ""
+
+#: src/components/product/InventoryProductForm.tsx:64
+#, c-format
+msgid "Quantity must be greater than 0!"
+msgstr ""
+
+#: src/components/product/InventoryProductForm.tsx:76
+#, c-format
+msgid ""
+"This quantity exceeds remaining stock. Currently, only %1$s units remain "
+"unreserved in stock."
+msgstr ""
+
+#: src/components/product/InventoryProductForm.tsx:109
+#, c-format
+msgid "Quantity"
+msgstr ""
+
+#: src/components/product/InventoryProductForm.tsx:110
+#, c-format
+msgid "how many products will be added"
+msgstr ""
+
+#: src/components/product/InventoryProductForm.tsx:117
+#, c-format
+msgid "Add from inventory"
+msgstr ""
+
+#: src/components/form/InputImage.tsx:105
+#, c-format
+msgid "Image should be smaller than 1 MB"
+msgstr ""
+
+#: src/components/form/InputImage.tsx:110
+#, c-format
+msgid "Add"
+msgstr ""
+
+#: src/components/form/InputImage.tsx:115
+#, c-format
+msgid "Remove"
+msgstr ""
+
+#: src/components/form/InputTaxes.tsx:113
+#, c-format
+msgid "No taxes configured for this product."
+msgstr ""
+
+#: src/components/form/InputTaxes.tsx:119
+#, c-format
+msgid "Amount"
+msgstr ""
+
+#: src/components/form/InputTaxes.tsx:120
+#, c-format
+msgid ""
+"Taxes can be in currencies that differ from the main currency used by the "
+"merchant."
+msgstr ""
+
+#: src/components/form/InputTaxes.tsx:122
+#, c-format
+msgid ""
+"Enter currency and value separated with a colon, e.g. &quot;USD:2.3&quot;."
+msgstr ""
+
+#: src/components/form/InputTaxes.tsx:131
+#, c-format
+msgid "Legal name of the tax, e.g. VAT or import duties."
+msgstr ""
+
+#: src/components/form/InputTaxes.tsx:137
+#, c-format
+msgid "add tax to the tax list"
+msgstr ""
+
+#: src/components/product/NonInventoryProductForm.tsx:72
+#, c-format
+msgid "describe and add a product that is not in the inventory list"
+msgstr ""
+
+#: src/components/product/NonInventoryProductForm.tsx:75
+#, c-format
+msgid "Add custom product"
+msgstr ""
+
+#: src/components/product/NonInventoryProductForm.tsx:86
+#, c-format
+msgid "Complete information of the product"
+msgstr ""
+
+#: src/components/product/NonInventoryProductForm.tsx:185
+#, c-format
+msgid "Image"
+msgstr ""
+
+#: src/components/product/NonInventoryProductForm.tsx:186
+#, c-format
+msgid "photo of the product"
+msgstr ""
+
+#: src/components/product/NonInventoryProductForm.tsx:192
+#, c-format
+msgid "full product description"
+msgstr ""
+
+#: src/components/product/NonInventoryProductForm.tsx:196
+#, c-format
+msgid "Unit"
+msgstr ""
+
+#: src/components/product/NonInventoryProductForm.tsx:197
+#, c-format
+msgid "name of the product unit"
+msgstr ""
+
+#: src/components/product/NonInventoryProductForm.tsx:201
+#, c-format
+msgid "Price"
+msgstr ""
+
+#: src/components/product/NonInventoryProductForm.tsx:202
+#, c-format
+msgid "amount in the current currency"
+msgstr ""
+
+#: src/components/product/NonInventoryProductForm.tsx:211
+#, c-format
+msgid "Taxes"
+msgstr ""
+
+#: src/components/product/ProductList.tsx:38
+#, c-format
+msgid "image"
+msgstr ""
+
+#: src/components/product/ProductList.tsx:41
+#, c-format
+msgid "description"
+msgstr ""
+
+#: src/components/product/ProductList.tsx:44
+#, c-format
+msgid "quantity"
+msgstr ""
+
+#: src/components/product/ProductList.tsx:47
+#, c-format
+msgid "unit price"
+msgstr ""
+
+#: src/components/product/ProductList.tsx:50
+#, c-format
+msgid "total price"
+msgstr ""
+
+#: src/paths/instance/orders/create/CreatePage.tsx:153
+#, c-format
+msgid "required"
+msgstr ""
+
+#: src/paths/instance/orders/create/CreatePage.tsx:157
+#, c-format
+msgid "not valid"
+msgstr ""
+
+#: src/paths/instance/orders/create/CreatePage.tsx:159
+#, c-format
+msgid "must be greater than 0"
+msgstr ""
+
+#: src/paths/instance/orders/create/CreatePage.tsx:164
+#, c-format
+msgid "not a valid json"
+msgstr ""
+
+#: src/paths/instance/orders/create/CreatePage.tsx:170
+#, c-format
+msgid "should be in the future"
+msgstr ""
+
+#: src/paths/instance/orders/create/CreatePage.tsx:173
+#, c-format
+msgid "refund deadline cannot be before pay deadline"
+msgstr ""
+
+#: src/paths/instance/orders/create/CreatePage.tsx:179
+#, c-format
+msgid "wire transfer deadline cannot be before refund deadline"
+msgstr ""
+
+#: src/paths/instance/orders/create/CreatePage.tsx:190
+#, c-format
+msgid "wire transfer deadline cannot be before pay deadline"
+msgstr ""
+
+#: src/paths/instance/orders/create/CreatePage.tsx:197
+#, c-format
+msgid "should have a refund deadline"
+msgstr ""
+
+#: src/paths/instance/orders/create/CreatePage.tsx:202
+#, c-format
+msgid "auto refund cannot be after refund deadline"
+msgstr ""
+
+#: src/paths/instance/orders/create/CreatePage.tsx:360
+#, c-format
+msgid "Manage products in order"
+msgstr ""
+
+#: src/paths/instance/orders/create/CreatePage.tsx:369
+#, c-format
+msgid "Manage list of products in the order."
+msgstr ""
+
+#: src/paths/instance/orders/create/CreatePage.tsx:391
+#, c-format
+msgid "Remove this product from the order."
+msgstr ""
+
+#: src/paths/instance/orders/create/CreatePage.tsx:415
+#, c-format
+msgid "Total price"
+msgstr ""
+
+#: src/paths/instance/orders/create/CreatePage.tsx:417
+#, c-format
+msgid "total product price added up"
+msgstr ""
+
+#: src/paths/instance/orders/create/CreatePage.tsx:430
+#, c-format
+msgid "Amount to be paid by the customer"
+msgstr ""
+
+#: src/paths/instance/orders/create/CreatePage.tsx:436
+#, c-format
+msgid "Order price"
+msgstr ""
+
+#: src/paths/instance/orders/create/CreatePage.tsx:437
+#, c-format
+msgid "final order price"
+msgstr ""
+
+#: src/paths/instance/orders/create/CreatePage.tsx:444
+#, c-format
+msgid "Summary"
+msgstr ""
+
+#: src/paths/instance/orders/create/CreatePage.tsx:445
+#, c-format
+msgid "Title of the order to be shown to the customer"
+msgstr ""
+
+#: src/paths/instance/orders/create/CreatePage.tsx:450
+#, c-format
+msgid "Shipping and Fulfillment"
+msgstr ""
+
+#: src/paths/instance/orders/create/CreatePage.tsx:455
+#, c-format
+msgid "Delivery date"
+msgstr ""
+
+#: src/paths/instance/orders/create/CreatePage.tsx:456
+#, c-format
+msgid "Deadline for physical delivery assured by the merchant."
+msgstr ""
+
+#: src/paths/instance/orders/create/CreatePage.tsx:461
+#, c-format
+msgid "Location"
+msgstr ""
+
+#: src/paths/instance/orders/create/CreatePage.tsx:462
+#, c-format
+msgid "address where the products will be delivered"
+msgstr ""
+
+#: src/paths/instance/orders/create/CreatePage.tsx:469
+#, c-format
+msgid "Fulfillment URL"
+msgstr ""
+
+#: src/paths/instance/orders/create/CreatePage.tsx:470
+#, c-format
+msgid "URL to which the user will be redirected after successful payment."
+msgstr ""
+
+#: src/paths/instance/orders/create/CreatePage.tsx:476
+#, c-format
+msgid "Taler payment options"
+msgstr ""
+
+#: src/paths/instance/orders/create/CreatePage.tsx:477
+#, c-format
+msgid "Override default Taler payment settings for this order"
+msgstr ""
+
+#: src/paths/instance/orders/create/CreatePage.tsx:481
+#, c-format
+msgid "Payment deadline"
+msgstr ""
+
+#: src/paths/instance/orders/create/CreatePage.tsx:482
+#, c-format
+msgid ""
+"Deadline for the customer to pay for the offer before it expires. Inventory "
+"products will be reserved until this deadline."
+msgstr ""
+
+#: src/paths/instance/orders/create/CreatePage.tsx:486
+#, c-format
+msgid "Refund deadline"
+msgstr ""
+
+#: src/paths/instance/orders/create/CreatePage.tsx:487
+#, c-format
+msgid "Time until which the order can be refunded by the merchant."
+msgstr ""
+
+#: src/paths/instance/orders/create/CreatePage.tsx:491
+#, c-format
+msgid "Wire transfer deadline"
+msgstr ""
+
+#: src/paths/instance/orders/create/CreatePage.tsx:492
+#, c-format
+msgid "Deadline for the exchange to make the wire transfer."
+msgstr ""
+
+#: src/paths/instance/orders/create/CreatePage.tsx:496
+#, c-format
+msgid "Auto-refund deadline"
+msgstr ""
+
+#: src/paths/instance/orders/create/CreatePage.tsx:497
+#, c-format
+msgid ""
+"Time until which the wallet will automatically check for refunds without "
+"user interaction."
+msgstr ""
+
+#: src/paths/instance/orders/create/CreatePage.tsx:502
+#, c-format
+msgid "Maximum deposit fee"
+msgstr ""
+
+#: src/paths/instance/orders/create/CreatePage.tsx:503
+#, c-format
+msgid ""
+"Maximum deposit fees the merchant is willing to cover for this order. Higher "
+"deposit fees must be covered in full by the consumer."
+msgstr ""
+
+#: src/paths/instance/orders/create/CreatePage.tsx:507
+#, c-format
+msgid "Maximum wire fee"
+msgstr ""
+
+#: src/paths/instance/orders/create/CreatePage.tsx:508
+#, c-format
+msgid ""
+"Maximum aggregate wire fees the merchant is willing to cover for this order. "
+"Wire fees exceeding this amount are to be covered by the customers."
+msgstr ""
+
+#: src/paths/instance/orders/create/CreatePage.tsx:512
+#, c-format
+msgid "Wire fee amortization"
+msgstr ""
+
+#: src/paths/instance/orders/create/CreatePage.tsx:513
+#, c-format
+msgid ""
+"Factor by which wire fees exceeding the above threshold are divided to "
+"determine the share of excess wire fees to be paid explicitly by the "
+"consumer."
+msgstr ""
+
+#: src/paths/instance/orders/create/CreatePage.tsx:517
+#, c-format
+msgid "Create token"
+msgstr ""
+
+#: src/paths/instance/orders/create/CreatePage.tsx:518
+#, c-format
+msgid ""
+"Uncheck this option if the merchant backend generated an order ID with "
+"enough entropy to prevent adversarial claims."
+msgstr ""
+
+#: src/paths/instance/orders/create/CreatePage.tsx:522
+#, c-format
+msgid "Minimum age required"
+msgstr ""
+
+#: src/paths/instance/orders/create/CreatePage.tsx:523
+#, c-format
+msgid ""
+"Any value greater than 0 will limit the coins able be used to pay this "
+"contract. If empty the age restriction will be defined by the products"
+msgstr ""
+
+#: src/paths/instance/orders/create/CreatePage.tsx:526
+#, c-format
+msgid "Min age defined by the producs is %1$s"
+msgstr ""
+
+#: src/paths/instance/orders/create/CreatePage.tsx:534
+#, c-format
+msgid "Additional information"
+msgstr ""
+
+#: src/paths/instance/orders/create/CreatePage.tsx:535
+#, c-format
+msgid "Custom information to be included in the contract for this order."
+msgstr ""
+
+#: src/paths/instance/orders/create/CreatePage.tsx:541
+#, c-format
+msgid "You must enter a value in JavaScript Object Notation (JSON)."
+msgstr ""
+
+#: src/components/picker/DurationPicker.tsx:55
+#, c-format
+msgid "days"
+msgstr ""
+
+#: src/components/picker/DurationPicker.tsx:65
+#, c-format
+msgid "hours"
+msgstr ""
+
+#: src/components/picker/DurationPicker.tsx:76
+#, c-format
+msgid "minutes"
+msgstr ""
+
+#: src/components/picker/DurationPicker.tsx:87
+#, c-format
+msgid "seconds"
+msgstr ""
+
+#: src/components/form/InputDuration.tsx:53
+#, c-format
+msgid "forever"
+msgstr ""
+
+#: src/components/form/InputDuration.tsx:62
+#, c-format
+msgid "%1$sM"
+msgstr ""
+
+#: src/components/form/InputDuration.tsx:64
+#, c-format
+msgid "%1$sY"
+msgstr ""
+
+#: src/components/form/InputDuration.tsx:66
+#, c-format
+msgid "%1$sd"
+msgstr ""
+
+#: src/components/form/InputDuration.tsx:68
+#, c-format
+msgid "%1$sh"
+msgstr ""
+
+#: src/components/form/InputDuration.tsx:70
+#, c-format
+msgid "%1$smin"
+msgstr ""
+
+#: src/components/form/InputDuration.tsx:72
+#, c-format
+msgid "%1$ssec"
+msgstr ""
+
+#: src/paths/instance/orders/list/Table.tsx:75
+#, c-format
+msgid "Orders"
+msgstr ""
+
+#: src/paths/instance/orders/list/Table.tsx:81
+#, c-format
+msgid "create order"
+msgstr ""
+
+#: src/paths/instance/orders/list/Table.tsx:147
+#, c-format
+msgid "load newer orders"
+msgstr ""
+
+#: src/paths/instance/orders/list/Table.tsx:154
+#, c-format
+msgid "Date"
+msgstr ""
+
+#: src/paths/instance/orders/list/Table.tsx:200
+#, c-format
+msgid "Refund"
+msgstr ""
+
+#: src/paths/instance/orders/list/Table.tsx:209
+#, c-format
+msgid "copy url"
+msgstr ""
+
+#: src/paths/instance/orders/list/Table.tsx:225
+#, c-format
+msgid "load older orders"
+msgstr ""
+
+#: src/paths/instance/orders/list/Table.tsx:242
+#, c-format
+msgid "No orders have been found matching your query!"
+msgstr ""
+
+#: src/paths/instance/orders/list/Table.tsx:288
+#, c-format
+msgid "duplicated"
+msgstr ""
+
+#: src/paths/instance/orders/list/Table.tsx:299
+#, c-format
+msgid "invalid format"
+msgstr ""
+
+#: src/paths/instance/orders/list/Table.tsx:301
+#, c-format
+msgid "this value exceed the refundable amount"
+msgstr ""
+
+#: src/paths/instance/orders/list/Table.tsx:346
+#, c-format
+msgid "date"
+msgstr ""
+
+#: src/paths/instance/orders/list/Table.tsx:349
+#, c-format
+msgid "amount"
+msgstr ""
+
+#: src/paths/instance/orders/list/Table.tsx:352
+#, c-format
+msgid "reason"
+msgstr ""
+
+#: src/paths/instance/orders/list/Table.tsx:389
+#, c-format
+msgid "amount to be refunded"
+msgstr ""
+
+#: src/paths/instance/orders/list/Table.tsx:391
+#, c-format
+msgid "Max refundable:"
+msgstr ""
+
+#: src/paths/instance/orders/list/Table.tsx:396
+#, c-format
+msgid "Reason"
+msgstr ""
+
+#: src/paths/instance/orders/list/Table.tsx:397
+#, c-format
+msgid "Choose one..."
+msgstr ""
+
+#: src/paths/instance/orders/list/Table.tsx:399
+#, c-format
+msgid "requested by the customer"
+msgstr ""
+
+#: src/paths/instance/orders/list/Table.tsx:400
+#, c-format
+msgid "other"
+msgstr ""
+
+#: src/paths/instance/orders/list/Table.tsx:403
+#, c-format
+msgid "why this order is being refunded"
+msgstr ""
+
+#: src/paths/instance/orders/list/Table.tsx:409
+#, c-format
+msgid "more information to give context"
+msgstr ""
+
+#: src/paths/instance/orders/details/DetailPage.tsx:62
+#, c-format
+msgid "Contract Terms"
+msgstr ""
+
+#: src/paths/instance/orders/details/DetailPage.tsx:68
+#, c-format
+msgid "human-readable description of the whole purchase"
+msgstr ""
+
+#: src/paths/instance/orders/details/DetailPage.tsx:74
+#, c-format
+msgid "total price for the transaction"
+msgstr ""
+
+#: src/paths/instance/orders/details/DetailPage.tsx:81
+#, c-format
+msgid "URL for this purchase"
+msgstr ""
+
+#: src/paths/instance/orders/details/DetailPage.tsx:87
+#, c-format
+msgid "Max fee"
+msgstr ""
+
+#: src/paths/instance/orders/details/DetailPage.tsx:88
+#, c-format
+msgid "maximum total deposit fee accepted by the merchant for this contract"
+msgstr ""
+
+#: src/paths/instance/orders/details/DetailPage.tsx:93
+#, c-format
+msgid "Max wire fee"
+msgstr ""
+
+#: src/paths/instance/orders/details/DetailPage.tsx:94
+#, c-format
+msgid "maximum wire fee accepted by the merchant"
+msgstr ""
+
+#: src/paths/instance/orders/details/DetailPage.tsx:100
+#, c-format
+msgid ""
+"over how many customer transactions does the merchant expect to amortize "
+"wire fees on average"
+msgstr ""
+
+#: src/paths/instance/orders/details/DetailPage.tsx:105
+#, c-format
+msgid "Created at"
+msgstr ""
+
+#: src/paths/instance/orders/details/DetailPage.tsx:106
+#, c-format
+msgid "time when this contract was generated"
+msgstr ""
+
+#: src/paths/instance/orders/details/DetailPage.tsx:112
+#, c-format
+msgid "after this deadline has passed no refunds will be accepted"
+msgstr ""
+
+#: src/paths/instance/orders/details/DetailPage.tsx:118
+#, c-format
+msgid ""
+"after this deadline, the merchant won't accept payments for the contract"
+msgstr ""
+
+#: src/paths/instance/orders/details/DetailPage.tsx:124
+#, c-format
+msgid "transfer deadline for the exchange"
+msgstr ""
+
+#: src/paths/instance/orders/details/DetailPage.tsx:130
+#, c-format
+msgid "time indicating when the order should be delivered"
+msgstr ""
+
+#: src/paths/instance/orders/details/DetailPage.tsx:136
+#, c-format
+msgid "where the order will be delivered"
+msgstr ""
+
+#: src/paths/instance/orders/details/DetailPage.tsx:144
+#, c-format
+msgid "Auto-refund delay"
+msgstr ""
+
+#: src/paths/instance/orders/details/DetailPage.tsx:145
+#, c-format
+msgid ""
+"how long the wallet should try to get an automatic refund for the purchase"
+msgstr ""
+
+#: src/paths/instance/orders/details/DetailPage.tsx:150
+#, c-format
+msgid "Extra info"
+msgstr ""
+
+#: src/paths/instance/orders/details/DetailPage.tsx:151
+#, c-format
+msgid "extra data that is only interpreted by the merchant frontend"
+msgstr ""
+
+#: src/paths/instance/orders/details/DetailPage.tsx:219
+#, c-format
+msgid "Order"
+msgstr ""
+
+#: src/paths/instance/orders/details/DetailPage.tsx:221
+#, c-format
+msgid "claimed"
+msgstr ""
+
+#: src/paths/instance/orders/details/DetailPage.tsx:247
+#, c-format
+msgid "claimed at"
+msgstr ""
+
+#: src/paths/instance/orders/details/DetailPage.tsx:265
+#, c-format
+msgid "Timeline"
+msgstr ""
+
+#: src/paths/instance/orders/details/DetailPage.tsx:271
+#, c-format
+msgid "Payment details"
+msgstr ""
+
+#: src/paths/instance/orders/details/DetailPage.tsx:291
+#, c-format
+msgid "Order status"
+msgstr ""
+
+#: src/paths/instance/orders/details/DetailPage.tsx:301
+#, c-format
+msgid "Product list"
+msgstr ""
+
+#: src/paths/instance/orders/details/DetailPage.tsx:451
+#, c-format
+msgid "paid"
+msgstr ""
+
+#: src/paths/instance/orders/details/DetailPage.tsx:455
+#, c-format
+msgid "wired"
+msgstr ""
+
+#: src/paths/instance/orders/details/DetailPage.tsx:460
+#, c-format
+msgid "refunded"
+msgstr ""
+
+#: src/paths/instance/orders/details/DetailPage.tsx:480
+#, c-format
+msgid "refund order"
+msgstr ""
+
+#: src/paths/instance/orders/details/DetailPage.tsx:481
+#, c-format
+msgid "not refundable"
+msgstr ""
+
+#: src/paths/instance/orders/details/DetailPage.tsx:489
+#, c-format
+msgid "refund"
+msgstr ""
+
+#: src/paths/instance/orders/details/DetailPage.tsx:553
+#, c-format
+msgid "Refunded amount"
+msgstr ""
+
+#: src/paths/instance/orders/details/DetailPage.tsx:560
+#, c-format
+msgid "Refund taken"
+msgstr ""
+
+#: src/paths/instance/orders/details/DetailPage.tsx:570
+#, c-format
+msgid "Status URL"
+msgstr ""
+
+#: src/paths/instance/orders/details/DetailPage.tsx:583
+#, c-format
+msgid "Refund URI"
+msgstr ""
+
+#: src/paths/instance/orders/details/DetailPage.tsx:636
+#, c-format
+msgid "unpaid"
+msgstr ""
+
+#: src/paths/instance/orders/details/DetailPage.tsx:654
+#, c-format
+msgid "pay at"
+msgstr ""
+
+#: src/paths/instance/orders/details/DetailPage.tsx:666
+#, c-format
+msgid "created at"
+msgstr ""
+
+#: src/paths/instance/orders/details/DetailPage.tsx:707
+#, c-format
+msgid "Order status URL"
+msgstr ""
+
+#: src/paths/instance/orders/details/DetailPage.tsx:711
+#, c-format
+msgid "Payment URI"
+msgstr ""
+
+#: src/paths/instance/orders/details/DetailPage.tsx:740
+#, c-format
+msgid ""
+"Unknown order status. This is an error, please contact the administrator."
+msgstr ""
+
+#: src/paths/instance/orders/details/DetailPage.tsx:767
+#, c-format
+msgid "Back"
+msgstr ""
+
+#: src/paths/instance/orders/details/index.tsx:79
+#, c-format
+msgid "refund created successfully"
+msgstr ""
+
+#: src/paths/instance/orders/details/index.tsx:85
+#, c-format
+msgid "could not create the refund"
+msgstr ""
+
+#: src/paths/instance/orders/list/ListPage.tsx:78
+#, c-format
+msgid "select date to show nearby orders"
+msgstr ""
+
+#: src/paths/instance/orders/list/ListPage.tsx:94
+#, c-format
+msgid "order id"
+msgstr ""
+
+#: src/paths/instance/orders/list/ListPage.tsx:100
+#, c-format
+msgid "jump to order with the given order ID"
+msgstr ""
+
+#: src/paths/instance/orders/list/ListPage.tsx:122
+#, c-format
+msgid "remove all filters"
+msgstr ""
+
+#: src/paths/instance/orders/list/ListPage.tsx:132
+#, c-format
+msgid "only show paid orders"
+msgstr ""
+
+#: src/paths/instance/orders/list/ListPage.tsx:135
+#, c-format
+msgid "Paid"
+msgstr ""
+
+#: src/paths/instance/orders/list/ListPage.tsx:142
+#, c-format
+msgid "only show orders with refunds"
+msgstr ""
+
+#: src/paths/instance/orders/list/ListPage.tsx:145
+#, c-format
+msgid "Refunded"
+msgstr ""
+
+#: src/paths/instance/orders/list/ListPage.tsx:152
+#, c-format
+msgid ""
+"only show orders where customers paid, but wire payments from payment "
+"provider are still pending"
+msgstr ""
+
+#: src/paths/instance/orders/list/ListPage.tsx:155
+#, c-format
+msgid "Not wired"
+msgstr ""
+
+#: src/paths/instance/orders/list/ListPage.tsx:170
+#, c-format
+msgid "clear date filter"
+msgstr ""
+
+#: src/paths/instance/orders/list/ListPage.tsx:184
+#, c-format
+msgid "date (YYYY/MM/DD)"
+msgstr ""
+
+#: src/paths/instance/orders/list/index.tsx:103
+#, c-format
+msgid "Enter an order id"
+msgstr ""
+
+#: src/paths/instance/orders/list/index.tsx:111
+#, c-format
+msgid "order not found"
+msgstr ""
+
+#: src/paths/instance/orders/list/index.tsx:178
+#, c-format
+msgid "could not get the order to refund"
+msgstr ""
+
+#: src/components/exception/AsyncButton.tsx:43
+#, c-format
+msgid "Loading..."
+msgstr ""
+
+#: src/components/form/InputStock.tsx:99
+#, c-format
+msgid ""
+"click here to configure the stock of the product, leave it as is and the "
+"backend will not control stock"
+msgstr ""
+
+#: src/components/form/InputStock.tsx:109
+#, c-format
+msgid "Manage stock"
+msgstr ""
+
+#: src/components/form/InputStock.tsx:115
+#, c-format
+msgid "this product has been configured without stock control"
+msgstr ""
+
+#: src/components/form/InputStock.tsx:119
+#, c-format
+msgid "Infinite"
+msgstr ""
+
+#: src/components/form/InputStock.tsx:136
+#, c-format
+msgid "lost cannot be greater than current and incoming (max %1$s)"
+msgstr ""
+
+#: src/components/form/InputStock.tsx:176
+#, c-format
+msgid "Incoming"
+msgstr ""
+
+#: src/components/form/InputStock.tsx:177
+#, c-format
+msgid "Lost"
+msgstr ""
+
+#: src/components/form/InputStock.tsx:192
+#, c-format
+msgid "Current"
+msgstr ""
+
+#: src/components/form/InputStock.tsx:196
+#, c-format
+msgid "remove stock control for this product"
+msgstr ""
+
+#: src/components/form/InputStock.tsx:202
+#, c-format
+msgid "without stock"
+msgstr ""
+
+#: src/components/form/InputStock.tsx:211
+#, c-format
+msgid "Next restock"
+msgstr ""
+
+#: src/components/form/InputStock.tsx:217
+#, c-format
+msgid "Delivery address"
+msgstr ""
+
+#: src/components/product/ProductForm.tsx:133
+#, c-format
+msgid "product identification to use in URLs (for internal use only)"
+msgstr ""
+
+#: src/components/product/ProductForm.tsx:139
+#, c-format
+msgid "illustration of the product for customers"
+msgstr ""
+
+#: src/components/product/ProductForm.tsx:145
+#, c-format
+msgid "product description for customers"
+msgstr ""
+
+#: src/components/product/ProductForm.tsx:149
+#, c-format
+msgid "Age restricted"
+msgstr ""
+
+#: src/components/product/ProductForm.tsx:150
+#, c-format
+msgid "is this product restricted for customer below certain age?"
+msgstr ""
+
+#: src/components/product/ProductForm.tsx:155
+#, c-format
+msgid ""
+"unit describing quantity of product sold (e.g. 2 kilograms, 5 liters, 3 "
+"items, 5 meters) for customers"
+msgstr ""
+
+#: src/components/product/ProductForm.tsx:160
+#, c-format
+msgid ""
+"sale price for customers, including taxes, for above units of the product"
+msgstr ""
+
+#: src/components/product/ProductForm.tsx:164
+#, c-format
+msgid "Stock"
+msgstr ""
+
+#: src/components/product/ProductForm.tsx:166
+#, c-format
+msgid ""
+"product inventory for products with finite supply (for internal use only)"
+msgstr ""
+
+#: src/components/product/ProductForm.tsx:171
+#, c-format
+msgid "taxes included in the product price, exposed to customers"
+msgstr ""
+
+#: src/paths/instance/products/create/CreatePage.tsx:66
+#, c-format
+msgid "Need to complete marked fields"
+msgstr ""
+
+#: src/paths/instance/products/create/index.tsx:51
+#, c-format
+msgid "could not create product"
+msgstr ""
+
+#: src/paths/instance/products/list/Table.tsx:68
+#, c-format
+msgid "Products"
+msgstr ""
+
+#: src/paths/instance/products/list/Table.tsx:73
+#, c-format
+msgid "add product to inventory"
+msgstr ""
+
+#: src/paths/instance/products/list/Table.tsx:137
+#, c-format
+msgid "Sell"
+msgstr ""
+
+#: src/paths/instance/products/list/Table.tsx:143
+#, c-format
+msgid "Profit"
+msgstr ""
+
+#: src/paths/instance/products/list/Table.tsx:149
+#, c-format
+msgid "Sold"
+msgstr ""
+
+#: src/paths/instance/products/list/Table.tsx:210
+#, c-format
+msgid "free"
+msgstr ""
+
+#: src/paths/instance/products/list/Table.tsx:248
+#, c-format
+msgid "go to product update page"
+msgstr ""
+
+#: src/paths/instance/products/list/Table.tsx:255
+#, c-format
+msgid "Update"
+msgstr ""
+
+#: src/paths/instance/products/list/Table.tsx:260
+#, c-format
+msgid "remove this product from the database"
+msgstr ""
+
+#: src/paths/instance/products/list/Table.tsx:331
+#, c-format
+msgid "update the product with new price"
+msgstr ""
+
+#: src/paths/instance/products/list/Table.tsx:341
+#, c-format
+msgid "update product with new price"
+msgstr ""
+
+#: src/paths/instance/products/list/Table.tsx:399
+#, c-format
+msgid "add more elements to the inventory"
+msgstr ""
+
+#: src/paths/instance/products/list/Table.tsx:404
+#, c-format
+msgid "report elements lost in the inventory"
+msgstr ""
+
+#: src/paths/instance/products/list/Table.tsx:409
+#, c-format
+msgid "new price for the product"
+msgstr ""
+
+#: src/paths/instance/products/list/Table.tsx:421
+#, c-format
+msgid "the are value with errors"
+msgstr ""
+
+#: src/paths/instance/products/list/Table.tsx:422
+#, c-format
+msgid "update product with new stock and price"
+msgstr ""
+
+#: src/paths/instance/products/list/Table.tsx:463
+#, c-format
+msgid "There is no products yet, add more pressing the + sign"
+msgstr ""
+
+#: src/paths/instance/products/list/index.tsx:86
+#, c-format
+msgid "product updated successfully"
+msgstr ""
+
+#: src/paths/instance/products/list/index.tsx:92
+#, c-format
+msgid "could not update the product"
+msgstr ""
+
+#: src/paths/instance/products/list/index.tsx:103
+#, c-format
+msgid "product delete successfully"
+msgstr ""
+
+#: src/paths/instance/products/list/index.tsx:109
+#, c-format
+msgid "could not delete the product"
+msgstr ""
+
+#: src/paths/instance/products/update/UpdatePage.tsx:56
+#, c-format
+msgid "Product id:"
+msgstr ""
+
+#: src/paths/instance/reserves/create/CreatedSuccessfully.tsx:95
+#, c-format
+msgid ""
+"To complete the setup of the reserve, you must now initiate a wire transfer "
+"using the given wire transfer subject and crediting the specified amount to "
+"the indicated account of the exchange."
+msgstr ""
+
+#: src/paths/instance/reserves/create/CreatedSuccessfully.tsx:102
+#, c-format
+msgid "If your system supports RFC 8905, you can do this by opening this URI:"
+msgstr ""
+
+#: src/paths/instance/reserves/create/CreatePage.tsx:83
+#, c-format
+msgid "it should be greater than 0"
+msgstr ""
+
+#: src/paths/instance/reserves/create/CreatePage.tsx:88
+#, c-format
+msgid "must be a valid URL"
+msgstr ""
+
+#: src/paths/instance/reserves/create/CreatePage.tsx:107
+#, c-format
+msgid "Initial balance"
+msgstr ""
+
+#: src/paths/instance/reserves/create/CreatePage.tsx:108
+#, c-format
+msgid "balance prior to deposit"
+msgstr ""
+
+#: src/paths/instance/reserves/create/CreatePage.tsx:112
+#, c-format
+msgid "Exchange URL"
+msgstr ""
+
+#: src/paths/instance/reserves/create/CreatePage.tsx:113
+#, c-format
+msgid "URL of exchange"
+msgstr ""
+
+#: src/paths/instance/reserves/create/CreatePage.tsx:148
+#, c-format
+msgid "Next"
+msgstr ""
+
+#: src/paths/instance/reserves/create/CreatePage.tsx:186
+#, c-format
+msgid "Wire method"
+msgstr ""
+
+#: src/paths/instance/reserves/create/CreatePage.tsx:187
+#, c-format
+msgid "method to use for wire transfer"
+msgstr ""
+
+#: src/paths/instance/reserves/create/CreatePage.tsx:189
+#, c-format
+msgid "Select one wire method"
+msgstr ""
+
+#: src/paths/instance/reserves/create/index.tsx:62
+#, c-format
+msgid "could not create reserve"
+msgstr ""
+
+#: src/paths/instance/reserves/details/DetailPage.tsx:77
+#, c-format
+msgid "Valid until"
+msgstr ""
+
+#: src/paths/instance/reserves/details/DetailPage.tsx:82
+#, c-format
+msgid "Created balance"
+msgstr ""
+
+#: src/paths/instance/reserves/details/DetailPage.tsx:99
+#, c-format
+msgid "Exchange balance"
+msgstr ""
+
+#: src/paths/instance/reserves/details/DetailPage.tsx:104
+#, c-format
+msgid "Picked up"
+msgstr ""
+
+#: src/paths/instance/reserves/details/DetailPage.tsx:109
+#, c-format
+msgid "Committed"
+msgstr ""
+
+#: src/paths/instance/reserves/details/DetailPage.tsx:116
+#, c-format
+msgid "Account address"
+msgstr ""
+
+#: src/paths/instance/reserves/details/DetailPage.tsx:119
+#, c-format
+msgid "Subject"
+msgstr ""
+
+#: src/paths/instance/reserves/details/DetailPage.tsx:130
+#, c-format
+msgid "Tips"
+msgstr ""
+
+#: src/paths/instance/reserves/details/DetailPage.tsx:193
+#, c-format
+msgid "No tips has been authorized from this reserve"
+msgstr ""
+
+#: src/paths/instance/reserves/details/DetailPage.tsx:213
+#, c-format
+msgid "Authorized"
+msgstr ""
+
+#: src/paths/instance/reserves/details/DetailPage.tsx:222
+#, c-format
+msgid "Expiration"
+msgstr ""
+
+#: src/paths/instance/reserves/list/AutorizeTipModal.tsx:108
+#, c-format
+msgid "amount of tip"
+msgstr ""
+
+#: src/paths/instance/reserves/list/AutorizeTipModal.tsx:112
+#, c-format
+msgid "Justification"
+msgstr ""
+
+#: src/paths/instance/reserves/list/AutorizeTipModal.tsx:114
+#, c-format
+msgid "reason for the tip"
+msgstr ""
+
+#: src/paths/instance/reserves/list/AutorizeTipModal.tsx:118
+#, c-format
+msgid "URL after tip"
+msgstr ""
+
+#: src/paths/instance/reserves/list/AutorizeTipModal.tsx:119
+#, c-format
+msgid "URL to visit after tip payment"
+msgstr ""
+
+#: src/paths/instance/reserves/list/Table.tsx:65
+#, c-format
+msgid "Reserves not yet funded"
+msgstr ""
+
+#: src/paths/instance/reserves/list/Table.tsx:89
+#, c-format
+msgid "Reserves ready"
+msgstr ""
+
+#: src/paths/instance/reserves/list/Table.tsx:95
+#, c-format
+msgid "add new reserve"
+msgstr ""
+
+#: src/paths/instance/reserves/list/Table.tsx:143
+#, c-format
+msgid "Expires at"
+msgstr ""
+
+#: src/paths/instance/reserves/list/Table.tsx:146
+#, c-format
+msgid "Initial"
+msgstr ""
+
+#: src/paths/instance/reserves/list/Table.tsx:202
+#, c-format
+msgid "delete selected reserve from the database"
+msgstr ""
+
+#: src/paths/instance/reserves/list/Table.tsx:210
+#, c-format
+msgid "authorize new tip from selected reserve"
+msgstr ""
+
+#: src/paths/instance/reserves/list/Table.tsx:237
+#, c-format
+msgid ""
+"There is no ready reserves yet, add more pressing the + sign or fund them"
+msgstr ""
+
+#: src/paths/instance/reserves/list/Table.tsx:264
+#, c-format
+msgid "Expected Balance"
+msgstr ""
+
+#: src/paths/instance/reserves/list/index.tsx:110
+#, c-format
+msgid "could not create the tip"
+msgstr ""
+
+#: src/paths/instance/templates/create/CreatePage.tsx:77
+#, c-format
+msgid "should not be empty"
+msgstr ""
+
+#: src/paths/instance/templates/create/CreatePage.tsx:93
+#, c-format
+msgid "should be greater that 0"
+msgstr ""
+
+#: src/paths/instance/templates/create/CreatePage.tsx:96
+#, c-format
+msgid "can't be empty"
+msgstr ""
+
+#: src/paths/instance/templates/create/CreatePage.tsx:100
+#, c-format
+msgid "to short"
+msgstr ""
+
+#: src/paths/instance/templates/create/CreatePage.tsx:108
+#, c-format
+msgid "just letters and numbers from 2 to 7"
+msgstr ""
+
+#: src/paths/instance/templates/create/CreatePage.tsx:110
+#, c-format
+msgid "size of the key should be 32"
+msgstr ""
+
+#: src/paths/instance/templates/create/CreatePage.tsx:137
+#, c-format
+msgid "Identifier"
+msgstr ""
+
+#: src/paths/instance/templates/create/CreatePage.tsx:138
+#, c-format
+msgid "Name of the template in URLs."
+msgstr ""
+
+#: src/paths/instance/templates/create/CreatePage.tsx:144
+#, c-format
+msgid "Describe what this template stands for"
+msgstr ""
+
+#: src/paths/instance/templates/create/CreatePage.tsx:149
+#, c-format
+msgid "Fixed summary"
+msgstr ""
+
+#: src/paths/instance/templates/create/CreatePage.tsx:150
+#, c-format
+msgid "If specified, this template will create order with the same summary"
+msgstr ""
+
+#: src/paths/instance/templates/create/CreatePage.tsx:154
+#, c-format
+msgid "Fixed price"
+msgstr ""
+
+#: src/paths/instance/templates/create/CreatePage.tsx:155
+#, c-format
+msgid "If specified, this template will create order with the same price"
+msgstr ""
+
+#: src/paths/instance/templates/create/CreatePage.tsx:159
+#, c-format
+msgid "Minimum age"
+msgstr ""
+
+#: src/paths/instance/templates/create/CreatePage.tsx:161
+#, c-format
+msgid "Is this contract restricted to some age?"
+msgstr ""
+
+#: src/paths/instance/templates/create/CreatePage.tsx:165
+#, c-format
+msgid "Payment timeout"
+msgstr ""
+
+#: src/paths/instance/templates/create/CreatePage.tsx:167
+#, c-format
+msgid ""
+"How much time has the customer to complete the payment once the order was "
+"created."
+msgstr ""
+
+#: src/paths/instance/templates/create/CreatePage.tsx:171
+#, c-format
+msgid "Verification algorithm"
+msgstr ""
+
+#: src/paths/instance/templates/create/CreatePage.tsx:172
+#, c-format
+msgid "Algorithm to use to verify transaction in offline mode"
+msgstr ""
+
+#: src/paths/instance/templates/create/CreatePage.tsx:180
+#, c-format
+msgid "Point-of-sale key"
+msgstr ""
+
+#: src/paths/instance/templates/create/CreatePage.tsx:182
+#, c-format
+msgid "Useful to validate the purchase"
+msgstr ""
+
+#: src/paths/instance/templates/create/CreatePage.tsx:196
+#, c-format
+msgid "generate random secret key"
+msgstr ""
+
+#: src/paths/instance/templates/create/CreatePage.tsx:203
+#, c-format
+msgid "random"
+msgstr ""
+
+#: src/paths/instance/templates/create/CreatePage.tsx:208
+#, c-format
+msgid "show secret key"
+msgstr ""
+
+#: src/paths/instance/templates/create/CreatePage.tsx:209
+#, c-format
+msgid "hide secret key"
+msgstr ""
+
+#: src/paths/instance/templates/create/CreatePage.tsx:216
+#, c-format
+msgid "hide"
+msgstr ""
+
+#: src/paths/instance/templates/create/CreatePage.tsx:218
+#, c-format
+msgid "show"
+msgstr ""
+
+#: src/paths/instance/templates/create/index.tsx:52
+#, c-format
+msgid "could not inform template"
+msgstr ""
+
+#: src/paths/instance/templates/use/UsePage.tsx:54
+#, c-format
+msgid "Amount is required"
+msgstr ""
+
+#: src/paths/instance/templates/use/UsePage.tsx:58
+#, c-format
+msgid "Order summary is required"
+msgstr ""
+
+#: src/paths/instance/templates/use/UsePage.tsx:86
+#, c-format
+msgid "New order for template"
+msgstr ""
+
+#: src/paths/instance/templates/use/UsePage.tsx:108
+#, c-format
+msgid "Amount of the order"
+msgstr ""
+
+#: src/paths/instance/templates/use/UsePage.tsx:113
+#, c-format
+msgid "Order summary"
+msgstr ""
+
+#: src/paths/instance/templates/use/index.tsx:92
+#, c-format
+msgid "could not create order from template"
+msgstr ""
+
+#: src/paths/instance/templates/qr/QrPage.tsx:131
+#, c-format
+msgid ""
+"Here you can specify a default value for fields that are not fixed. Default "
+"values can be edited by the customer before the payment."
+msgstr ""
+
+#: src/paths/instance/templates/qr/QrPage.tsx:148
+#, c-format
+msgid "Fixed amount"
+msgstr ""
+
+#: src/paths/instance/templates/qr/QrPage.tsx:149
+#, c-format
+msgid "Default amount"
+msgstr ""
+
+#: src/paths/instance/templates/qr/QrPage.tsx:161
+#, c-format
+msgid "Default summary"
+msgstr ""
+
+#: src/paths/instance/templates/qr/QrPage.tsx:177
+#, c-format
+msgid "Print"
+msgstr ""
+
+#: src/paths/instance/templates/qr/QrPage.tsx:184
+#, c-format
+msgid "Setup TOTP"
+msgstr ""
+
+#: src/paths/instance/templates/list/Table.tsx:65
+#, c-format
+msgid "Templates"
+msgstr ""
+
+#: src/paths/instance/templates/list/Table.tsx:70
+#, c-format
+msgid "add new templates"
+msgstr ""
+
+#: src/paths/instance/templates/list/Table.tsx:142
+#, c-format
+msgid "load more templates before the first one"
+msgstr ""
+
+#: src/paths/instance/templates/list/Table.tsx:146
+#, c-format
+msgid "load newer templates"
+msgstr ""
+
+#: src/paths/instance/templates/list/Table.tsx:181
+#, c-format
+msgid "delete selected templates from the database"
+msgstr ""
+
+#: src/paths/instance/templates/list/Table.tsx:188
+#, c-format
+msgid "use template to create new order"
+msgstr ""
+
+#: src/paths/instance/templates/list/Table.tsx:195
+#, c-format
+msgid "create qr code for the template"
+msgstr ""
+
+#: src/paths/instance/templates/list/Table.tsx:210
+#, c-format
+msgid "load more templates after the last one"
+msgstr ""
+
+#: src/paths/instance/templates/list/Table.tsx:214
+#, c-format
+msgid "load older templates"
+msgstr ""
+
+#: src/paths/instance/templates/list/Table.tsx:231
+#, c-format
+msgid "There is no templates yet, add more pressing the + sign"
+msgstr ""
+
+#: src/paths/instance/templates/list/index.tsx:104
+#, c-format
+msgid "template delete successfully"
+msgstr ""
+
+#: src/paths/instance/templates/list/index.tsx:110
+#, c-format
+msgid "could not delete the template"
+msgstr ""
+
+#: src/paths/instance/templates/update/index.tsx:90
+#, c-format
+msgid "could not update template"
+msgstr ""
+
+#: src/paths/instance/webhooks/create/CreatePage.tsx:57
+#, c-format
+msgid "should be one of '%1$s'"
+msgstr ""
+
+#: src/paths/instance/webhooks/create/CreatePage.tsx:85
+#, c-format
+msgid "Webhook ID to use"
+msgstr ""
+
+#: src/paths/instance/webhooks/create/CreatePage.tsx:89
+#, c-format
+msgid "Event"
+msgstr ""
+
+#: src/paths/instance/webhooks/create/CreatePage.tsx:90
+#, c-format
+msgid "The event of the webhook: why the webhook is used"
+msgstr ""
+
+#: src/paths/instance/webhooks/create/CreatePage.tsx:94
+#, c-format
+msgid "Method"
+msgstr ""
+
+#: src/paths/instance/webhooks/create/CreatePage.tsx:95
+#, c-format
+msgid "Method used by the webhook"
+msgstr ""
+
+#: src/paths/instance/webhooks/create/CreatePage.tsx:99
+#, c-format
+msgid "URL"
+msgstr ""
+
+#: src/paths/instance/webhooks/create/CreatePage.tsx:100
+#, c-format
+msgid "URL of the webhook where the customer will be redirected"
+msgstr ""
+
+#: src/paths/instance/webhooks/create/CreatePage.tsx:104
+#, c-format
+msgid "Header"
+msgstr ""
+
+#: src/paths/instance/webhooks/create/CreatePage.tsx:106
+#, c-format
+msgid "Header template of the webhook"
+msgstr ""
+
+#: src/paths/instance/webhooks/create/CreatePage.tsx:111
+#, c-format
+msgid "Body"
+msgstr ""
+
+#: src/paths/instance/webhooks/create/CreatePage.tsx:112
+#, c-format
+msgid "Body template by the webhook"
+msgstr ""
+
+#: src/paths/instance/webhooks/list/Table.tsx:61
+#, c-format
+msgid "Webhooks"
+msgstr ""
+
+#: src/paths/instance/webhooks/list/Table.tsx:66
+#, c-format
+msgid "add new webhooks"
+msgstr ""
+
+#: src/paths/instance/webhooks/list/Table.tsx:137
+#, c-format
+msgid "load more webhooks before the first one"
+msgstr ""
+
+#: src/paths/instance/webhooks/list/Table.tsx:141
+#, c-format
+msgid "load newer webhooks"
+msgstr ""
+
+#: src/paths/instance/webhooks/list/Table.tsx:151
+#, c-format
+msgid "Event type"
+msgstr ""
+
+#: src/paths/instance/webhooks/list/Table.tsx:176
+#, c-format
+msgid "delete selected webhook from the database"
+msgstr ""
+
+#: src/paths/instance/webhooks/list/Table.tsx:198
+#, c-format
+msgid "load more webhooks after the last one"
+msgstr ""
+
+#: src/paths/instance/webhooks/list/Table.tsx:202
+#, c-format
+msgid "load older webhooks"
+msgstr ""
+
+#: src/paths/instance/webhooks/list/Table.tsx:219
+#, c-format
+msgid "There is no webhooks yet, add more pressing the + sign"
+msgstr ""
+
+#: src/paths/instance/webhooks/list/index.tsx:94
+#, c-format
+msgid "webhook delete successfully"
+msgstr ""
+
+#: src/paths/instance/webhooks/list/index.tsx:100
+#, c-format
+msgid "could not delete the webhook"
+msgstr ""
+
+#: src/paths/instance/transfers/create/CreatePage.tsx:63
+#, c-format
+msgid "check the id, does not look valid"
+msgstr ""
+
+#: src/paths/instance/transfers/create/CreatePage.tsx:65
+#, c-format
+msgid "should have 52 characters, current %1$s"
+msgstr ""
+
+#: src/paths/instance/transfers/create/CreatePage.tsx:72
+#, c-format
+msgid "URL doesn't have the right format"
+msgstr ""
+
+#: src/paths/instance/transfers/create/CreatePage.tsx:98
+#, c-format
+msgid "Credited bank account"
+msgstr ""
+
+#: src/paths/instance/transfers/create/CreatePage.tsx:100
+#, c-format
+msgid "Select one account"
+msgstr ""
+
+#: src/paths/instance/transfers/create/CreatePage.tsx:101
+#, c-format
+msgid "Bank account of the merchant where the payment was received"
+msgstr ""
+
+#: src/paths/instance/transfers/create/CreatePage.tsx:105
+#, c-format
+msgid "Wire transfer ID"
+msgstr ""
+
+#: src/paths/instance/transfers/create/CreatePage.tsx:107
+#, c-format
+msgid ""
+"unique identifier of the wire transfer used by the exchange, must be 52 "
+"characters long"
+msgstr ""
+
+#: src/paths/instance/transfers/create/CreatePage.tsx:112
+#, c-format
+msgid ""
+"Base URL of the exchange that made the transfer, should have been in the "
+"wire transfer subject"
+msgstr ""
+
+#: src/paths/instance/transfers/create/CreatePage.tsx:117
+#, c-format
+msgid "Amount credited"
+msgstr ""
+
+#: src/paths/instance/transfers/create/CreatePage.tsx:118
+#, c-format
+msgid "Actual amount that was wired to the merchant's bank account"
+msgstr ""
+
+#: src/paths/instance/transfers/create/index.tsx:58
+#, c-format
+msgid "could not inform transfer"
+msgstr ""
+
+#: src/paths/instance/transfers/list/Table.tsx:61
+#, c-format
+msgid "Transfers"
+msgstr ""
+
+#: src/paths/instance/transfers/list/Table.tsx:66
+#, c-format
+msgid "add new transfer"
+msgstr ""
+
+#: src/paths/instance/transfers/list/Table.tsx:129
+#, c-format
+msgid "load more transfers before the first one"
+msgstr ""
+
+#: src/paths/instance/transfers/list/Table.tsx:133
+#, c-format
+msgid "load newer transfers"
+msgstr ""
+
+#: src/paths/instance/transfers/list/Table.tsx:143
+#, c-format
+msgid "Credit"
+msgstr ""
+
+#: src/paths/instance/transfers/list/Table.tsx:152
+#, c-format
+msgid "Confirmed"
+msgstr ""
+
+#: src/paths/instance/transfers/list/Table.tsx:155
+#, c-format
+msgid "Verified"
+msgstr ""
+
+#: src/paths/instance/transfers/list/Table.tsx:158
+#, c-format
+msgid "Executed at"
+msgstr ""
+
+#: src/paths/instance/transfers/list/Table.tsx:171
+#, c-format
+msgid "yes"
+msgstr ""
+
+#: src/paths/instance/transfers/list/Table.tsx:171
+#, c-format
+msgid "no"
+msgstr ""
+
+#: src/paths/instance/transfers/list/Table.tsx:181
+#, c-format
+msgid "unknown"
+msgstr ""
+
+#: src/paths/instance/transfers/list/Table.tsx:187
+#, c-format
+msgid "delete selected transfer from the database"
+msgstr ""
+
+#: src/paths/instance/transfers/list/Table.tsx:202
+#, c-format
+msgid "load more transfer after the last one"
+msgstr ""
+
+#: src/paths/instance/transfers/list/Table.tsx:206
+#, c-format
+msgid "load older transfers"
+msgstr ""
+
+#: src/paths/instance/transfers/list/Table.tsx:223
+#, c-format
+msgid "There is no transfer yet, add more pressing the + sign"
+msgstr ""
+
+#: src/paths/instance/transfers/list/ListPage.tsx:79
+#, c-format
+msgid "filter by account address"
+msgstr ""
+
+#: src/paths/instance/transfers/list/ListPage.tsx:100
+#, c-format
+msgid "only show wire transfers confirmed by the merchant"
+msgstr ""
+
+#: src/paths/instance/transfers/list/ListPage.tsx:110
+#, c-format
+msgid "only show wire transfers claimed by the exchange"
+msgstr ""
+
+#: src/paths/instance/transfers/list/ListPage.tsx:113
+#, c-format
+msgid "Unverified"
+msgstr ""
+
+#: src/paths/admin/create/CreatePage.tsx:69
+#, c-format
+msgid "is not valid"
+msgstr ""
+
+#: src/paths/admin/create/CreatePage.tsx:94
+#, c-format
+msgid "is not a number"
+msgstr ""
+
+#: src/paths/admin/create/CreatePage.tsx:96
+#, c-format
+msgid "must be 1 or greater"
+msgstr ""
+
+#: src/paths/admin/create/CreatePage.tsx:107
+#, c-format
+msgid "max 7 lines"
+msgstr ""
+
+#: src/paths/admin/create/CreatePage.tsx:178
+#, c-format
+msgid "change authorization configuration"
+msgstr ""
+
+#: src/paths/admin/create/CreatePage.tsx:217
+#, c-format
+msgid "Need to complete marked fields and choose authorization method"
+msgstr ""
+
+#: src/components/form/InputPaytoForm.tsx:82
+#, c-format
+msgid "This is not a valid bitcoin address."
+msgstr ""
+
+#: src/components/form/InputPaytoForm.tsx:95
+#, c-format
+msgid "This is not a valid Ethereum address."
+msgstr ""
+
+#: src/components/form/InputPaytoForm.tsx:118
+#, c-format
+msgid "IBAN numbers usually have more that 4 digits"
+msgstr ""
+
+#: src/components/form/InputPaytoForm.tsx:120
+#, c-format
+msgid "IBAN numbers usually have less that 34 digits"
+msgstr ""
+
+#: src/components/form/InputPaytoForm.tsx:128
+#, c-format
+msgid "IBAN country code not found"
+msgstr ""
+
+#: src/components/form/InputPaytoForm.tsx:153
+#, c-format
+msgid "IBAN number is not valid, checksum is wrong"
+msgstr ""
+
+#: src/components/form/InputPaytoForm.tsx:248
+#, c-format
+msgid "Target type"
+msgstr ""
+
+#: src/components/form/InputPaytoForm.tsx:249
+#, c-format
+msgid "Method to use for wire transfer"
+msgstr ""
+
+#: src/components/form/InputPaytoForm.tsx:258
+#, c-format
+msgid "Routing"
+msgstr ""
+
+#: src/components/form/InputPaytoForm.tsx:259
+#, c-format
+msgid "Routing number."
+msgstr ""
+
+#: src/components/form/InputPaytoForm.tsx:263
+#, c-format
+msgid "Account"
+msgstr ""
+
+#: src/components/form/InputPaytoForm.tsx:264
+#, c-format
+msgid "Account number."
+msgstr ""
+
+#: src/components/form/InputPaytoForm.tsx:273
+#, c-format
+msgid "Business Identifier Code."
+msgstr ""
+
+#: src/components/form/InputPaytoForm.tsx:282
+#, c-format
+msgid "Bank Account Number."
+msgstr ""
+
+#: src/components/form/InputPaytoForm.tsx:292
+#, c-format
+msgid "Unified Payment Interface."
+msgstr ""
+
+#: src/components/form/InputPaytoForm.tsx:301
+#, c-format
+msgid "Bitcoin protocol."
+msgstr ""
+
+#: src/components/form/InputPaytoForm.tsx:310
+#, c-format
+msgid "Ethereum protocol."
+msgstr ""
+
+#: src/components/form/InputPaytoForm.tsx:319
+#, c-format
+msgid "Interledger protocol."
+msgstr ""
+
+#: src/components/form/InputPaytoForm.tsx:328
+#, c-format
+msgid "Host"
+msgstr ""
+
+#: src/components/form/InputPaytoForm.tsx:329
+#, c-format
+msgid "Bank host."
+msgstr ""
+
+#: src/components/form/InputPaytoForm.tsx:334
+#, c-format
+msgid "Bank account."
+msgstr ""
+
+#: src/components/form/InputPaytoForm.tsx:343
+#, c-format
+msgid "Bank account owner's name."
+msgstr ""
+
+#: src/components/form/InputPaytoForm.tsx:370
+#, c-format
+msgid "No accounts yet."
+msgstr ""
+
+#: src/components/instance/DefaultInstanceFormFields.tsx:52
+#, c-format
+msgid ""
+"Name of the instance in URLs. The 'default' instance is special in that it "
+"is used to administer other instances."
+msgstr ""
+
+#: src/components/instance/DefaultInstanceFormFields.tsx:58
+#, c-format
+msgid "Business name"
+msgstr ""
+
+#: src/components/instance/DefaultInstanceFormFields.tsx:59
+#, c-format
+msgid "Legal name of the business represented by this instance."
+msgstr ""
+
+#: src/components/instance/DefaultInstanceFormFields.tsx:64
+#, c-format
+msgid "Email"
+msgstr ""
+
+#: src/components/instance/DefaultInstanceFormFields.tsx:65
+#, c-format
+msgid "Contact email"
+msgstr ""
+
+#: src/components/instance/DefaultInstanceFormFields.tsx:70
+#, c-format
+msgid "Website URL"
+msgstr ""
+
+#: src/components/instance/DefaultInstanceFormFields.tsx:71
+#, c-format
+msgid "URL."
+msgstr ""
+
+#: src/components/instance/DefaultInstanceFormFields.tsx:76
+#, c-format
+msgid "Logo"
+msgstr ""
+
+#: src/components/instance/DefaultInstanceFormFields.tsx:77
+#, c-format
+msgid "Logo image."
+msgstr ""
+
+#: src/components/instance/DefaultInstanceFormFields.tsx:82
+#, c-format
+msgid "Bank account"
+msgstr ""
+
+#: src/components/instance/DefaultInstanceFormFields.tsx:83
+#, c-format
+msgid "URI specifying bank account for crediting revenue."
+msgstr ""
+
+#: src/components/instance/DefaultInstanceFormFields.tsx:88
+#, c-format
+msgid "Default max deposit fee"
+msgstr ""
+
+#: src/components/instance/DefaultInstanceFormFields.tsx:89
+#, c-format
+msgid ""
+"Maximum deposit fees this merchant is willing to pay per order by default."
+msgstr ""
+
+#: src/components/instance/DefaultInstanceFormFields.tsx:94
+#, c-format
+msgid "Default max wire fee"
+msgstr ""
+
+#: src/components/instance/DefaultInstanceFormFields.tsx:95
+#, c-format
+msgid ""
+"Maximum wire fees this merchant is willing to pay per wire transfer by "
+"default."
+msgstr ""
+
+#: src/components/instance/DefaultInstanceFormFields.tsx:100
+#, c-format
+msgid "Default wire fee amortization"
+msgstr ""
+
+#: src/components/instance/DefaultInstanceFormFields.tsx:101
+#, c-format
+msgid ""
+"Number of orders excess wire transfer fees will be divided by to compute per "
+"order surcharge."
+msgstr ""
+
+#: src/components/instance/DefaultInstanceFormFields.tsx:107
+#, c-format
+msgid "Physical location of the merchant."
+msgstr ""
+
+#: src/components/instance/DefaultInstanceFormFields.tsx:114
+#, c-format
+msgid "Jurisdiction"
+msgstr ""
+
+#: src/components/instance/DefaultInstanceFormFields.tsx:115
+#, c-format
+msgid "Jurisdiction for legal disputes with the merchant."
+msgstr ""
+
+#: src/components/instance/DefaultInstanceFormFields.tsx:122
+#, c-format
+msgid "Default payment delay"
+msgstr ""
+
+#: src/components/instance/DefaultInstanceFormFields.tsx:124
+#, c-format
+msgid ""
+"Time customers have to pay an order before the offer expires by default."
+msgstr ""
+
+#: src/components/instance/DefaultInstanceFormFields.tsx:129
+#, c-format
+msgid "Default wire transfer delay"
+msgstr ""
+
+#: src/components/instance/DefaultInstanceFormFields.tsx:130
+#, c-format
+msgid ""
+"Maximum time an exchange is allowed to delay wiring funds to the merchant, "
+"enabling it to aggregate smaller payments into larger wire transfers and "
+"reducing wire fees."
+msgstr ""
+
+#: src/paths/instance/update/UpdatePage.tsx:164
+#, c-format
+msgid "Instance id"
+msgstr ""
+
+#: src/paths/instance/update/UpdatePage.tsx:173
+#, c-format
+msgid "Change the authorization method use for this instance."
+msgstr ""
+
+#: src/paths/instance/update/UpdatePage.tsx:182
+#, c-format
+msgid "Manage access token"
+msgstr ""
+
+#: src/paths/instance/update/index.tsx:112
+#, c-format
+msgid "Failed to create instance"
+msgstr ""
+
+#: src/components/exception/login.tsx:74
+#, c-format
+msgid "Login required"
+msgstr ""
+
+#: src/components/exception/login.tsx:80
+#, c-format
+msgid "Please enter your access token."
+msgstr ""
+
+#: src/components/exception/login.tsx:108
+#, c-format
+msgid "Access Token"
+msgstr ""
+
+#: src/InstanceRoutes.tsx:171
+#, c-format
+msgid "The request to the backend take too long and was cancelled"
+msgstr ""
+
+#: src/InstanceRoutes.tsx:172
+#, c-format
+msgid "Diagnostic from %1$s is \"%2$s\""
+msgstr ""
+
+#: src/InstanceRoutes.tsx:178
+#, c-format
+msgid "The backend reported a problem: HTTP status #%1$s"
+msgstr ""
+
+#: src/InstanceRoutes.tsx:179
+#, c-format
+msgid "Diagnostic from %1$s is '%2$s'"
+msgstr ""
+
+#: src/InstanceRoutes.tsx:196
+#, c-format
+msgid "Access denied"
+msgstr ""
+
+#: src/InstanceRoutes.tsx:197
+#, c-format
+msgid "The access token provided is invalid."
+msgstr ""
+
+#: src/InstanceRoutes.tsx:212
+#, c-format
+msgid "No 'default' instance configured yet."
+msgstr ""
+
+#: src/InstanceRoutes.tsx:213
+#, c-format
+msgid "Create a 'default' instance to begin using the merchant backoffice."
+msgstr ""
+
+#: src/InstanceRoutes.tsx:630
+#, c-format
+msgid "The access token provided is invalid"
+msgstr ""
+
+#: src/InstanceRoutes.tsx:664
+#, c-format
+msgid "Hide for today"
+msgstr ""
+
+#: src/components/menu/SideBar.tsx:82
+#, c-format
+msgid "Instance"
+msgstr ""
+
+#: src/components/menu/SideBar.tsx:91
+#, c-format
+msgid "Settings"
+msgstr ""
+
+#: src/components/menu/SideBar.tsx:167
+#, c-format
+msgid "Connection"
+msgstr ""
+
+#: src/components/menu/SideBar.tsx:209
+#, c-format
+msgid "New"
+msgstr ""
+
+#: src/components/menu/SideBar.tsx:219
+#, c-format
+msgid "List"
+msgstr ""
+
+#: src/components/menu/SideBar.tsx:234
+#, c-format
+msgid "Log out"
+msgstr ""
+
+#: src/ApplicationReadyRoutes.tsx:71
+#, c-format
+msgid "Check your token is valid"
+msgstr ""
+
+#: src/ApplicationReadyRoutes.tsx:90
+#, c-format
+msgid "Couldn't access the server."
+msgstr ""
+
+#: src/ApplicationReadyRoutes.tsx:91
+#, c-format
+msgid "Could not infer instance id from url %1$s"
+msgstr ""
+
+#: src/Application.tsx:104
+#, c-format
+msgid "Server not found"
+msgstr ""
+
+#: src/Application.tsx:118
+#, c-format
+msgid "Server response with an error code"
+msgstr ""
+
+#: src/Application.tsx:120
+#, c-format
+msgid "Got message %1$s from %2$s"
+msgstr ""
+
+#: src/Application.tsx:131
+#, c-format
+msgid "Response from server is unreadable, http status: %1$s"
+msgstr ""
+
+#: src/Application.tsx:144
+#, c-format
+msgid "Unexpected Error"
+msgstr ""
+
+#: src/components/form/InputArray.tsx:101
+#, c-format
+msgid "The value %1$s is invalid for a payment url"
+msgstr ""
+
+#: src/components/form/InputArray.tsx:110
+#, c-format
+msgid "add element to the list"
+msgstr ""
+
+#: src/components/form/InputArray.tsx:112
+#, c-format
+msgid "add"
+msgstr ""
+
+#: src/components/form/InputSecured.tsx:37
+#, c-format
+msgid "Deleting"
+msgstr ""
+
+#: src/components/form/InputSecured.tsx:41
+#, c-format
+msgid "Changing"
+msgstr ""
+
+#: src/paths/instance/orders/create/OrderCreatedSuccessfully.tsx:87
+#, c-format
+msgid "Order ID"
+msgstr ""
+
+#: src/paths/instance/orders/create/OrderCreatedSuccessfully.tsx:101
+#, c-format
+msgid "Payment URL"
+msgstr ""
diff --git a/packages/auditor-backoffice-ui/src/i18n/it.po 
b/packages/auditor-backoffice-ui/src/i18n/it.po
new file mode 100644
index 000000000..4055af10e
--- /dev/null
+++ b/packages/auditor-backoffice-ui/src/i18n/it.po
@@ -0,0 +1,2742 @@
+# This file is part of TALER
+# (C) 2016 GNUnet e.V.
+#
+# TALER is free software; you can redistribute it and/or modify it under the
+# terms of the GNU General Public License as published by the Free Software
+# Foundation; either version 3, or (at your option) any later version.
+#
+# TALER is distributed in the hope that it will be useful, but WITHOUT ANY
+# WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
+# A PARTICULAR PURPOSE.  See the GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License along with
+# TALER; see the file COPYING.  If not, see <http://www.gnu.org/licenses/>
+#
+msgid ""
+msgstr ""
+"Project-Id-Version: Taler Wallet\n"
+"Report-Msgid-Bugs-To: taler@gnu.org\n"
+"POT-Creation-Date: 2016-11-23 00:00+0100\n"
+"PO-Revision-Date: 2023-08-16 12:43+0000\n"
+"Last-Translator: Krystian Baran <kiszkot@murena.io>\n"
+"Language-Team: Italian <https://weblate.taler.net/projects/gnu-taler/";
+"merchant-backoffice/it/>\n"
+"Language: it\n"
+"MIME-Version: 1.0\n"
+"Content-Type: text/plain; charset=UTF-8\n"
+"Content-Transfer-Encoding: 8bit\n"
+"Plural-Forms: nplurals=2; plural=n != 1;\n"
+"X-Generator: Weblate 4.13.1\n"
+
+#: src/components/modal/index.tsx:71
+#, c-format
+msgid "Cancel"
+msgstr ""
+
+#: src/components/modal/index.tsx:79
+#, c-format
+msgid "%1$s"
+msgstr ""
+
+#: src/components/modal/index.tsx:84
+#, c-format
+msgid "Close"
+msgstr ""
+
+#: src/components/modal/index.tsx:124
+#, c-format
+msgid "Continue"
+msgstr ""
+
+#: src/components/modal/index.tsx:178
+#, c-format
+msgid "Clear"
+msgstr ""
+
+#: src/components/modal/index.tsx:190
+#, c-format
+msgid "Confirm"
+msgstr ""
+
+#: src/components/modal/index.tsx:296
+#, c-format
+msgid "is not the same as the current access token"
+msgstr ""
+
+#: src/components/modal/index.tsx:299
+#, c-format
+msgid "cannot be empty"
+msgstr ""
+
+#: src/components/modal/index.tsx:301
+#, c-format
+msgid "cannot be the same as the old token"
+msgstr ""
+
+#: src/components/modal/index.tsx:305
+#, c-format
+msgid "is not the same"
+msgstr ""
+
+#: src/components/modal/index.tsx:315
+#, c-format
+msgid "You are updating the access token from instance with id %1$s"
+msgstr ""
+
+#: src/components/modal/index.tsx:331
+#, c-format
+msgid "Old access token"
+msgstr ""
+
+#: src/components/modal/index.tsx:332
+#, c-format
+msgid "access token currently in use"
+msgstr ""
+
+#: src/components/modal/index.tsx:338
+#, c-format
+msgid "New access token"
+msgstr ""
+
+#: src/components/modal/index.tsx:339
+#, c-format
+msgid "next access token to be used"
+msgstr ""
+
+#: src/components/modal/index.tsx:344
+#, c-format
+msgid "Repeat access token"
+msgstr ""
+
+#: src/components/modal/index.tsx:345
+#, c-format
+msgid "confirm the same access token"
+msgstr ""
+
+#: src/components/modal/index.tsx:350
+#, c-format
+msgid "Clearing the access token will mean public access to the instance"
+msgstr ""
+
+#: src/components/modal/index.tsx:377
+#, c-format
+msgid "cannot be the same as the old access token"
+msgstr ""
+
+#: src/components/modal/index.tsx:394
+#, c-format
+msgid "You are setting the access token for the new instance"
+msgstr ""
+
+#: src/components/modal/index.tsx:420
+#, c-format
+msgid ""
+"With external authorization method no check will be done by the merchant "
+"backend"
+msgstr ""
+
+#: src/components/modal/index.tsx:436
+#, c-format
+msgid "Set external authorization"
+msgstr ""
+
+#: src/components/modal/index.tsx:448
+#, c-format
+msgid "Set access token"
+msgstr ""
+
+#: src/components/modal/index.tsx:470
+#, c-format
+msgid "Operation in progress..."
+msgstr ""
+
+#: src/components/modal/index.tsx:479
+#, c-format
+msgid "The operation will be automatically canceled after %1$s seconds"
+msgstr ""
+
+#: src/paths/admin/list/TableActive.tsx:80
+#, c-format
+msgid "Instances"
+msgstr ""
+
+#: src/paths/admin/list/TableActive.tsx:93
+#, c-format
+msgid "Delete"
+msgstr ""
+
+#: src/paths/admin/list/TableActive.tsx:99
+#, c-format
+msgid "add new instance"
+msgstr ""
+
+#: src/paths/admin/list/TableActive.tsx:178
+#, c-format
+msgid "ID"
+msgstr ""
+
+#: src/paths/admin/list/TableActive.tsx:181
+#, c-format
+msgid "Name"
+msgstr ""
+
+#: src/paths/admin/list/TableActive.tsx:220
+#, c-format
+msgid "Edit"
+msgstr ""
+
+#: src/paths/admin/list/TableActive.tsx:237
+#, c-format
+msgid "Purge"
+msgstr ""
+
+#: src/paths/admin/list/TableActive.tsx:261
+#, c-format
+msgid "There is no instances yet, add more pressing the + sign"
+msgstr ""
+
+#: src/paths/admin/list/View.tsx:68
+#, c-format
+msgid "Only show active instances"
+msgstr ""
+
+#: src/paths/admin/list/View.tsx:71
+#, c-format
+msgid "Active"
+msgstr ""
+
+#: src/paths/admin/list/View.tsx:78
+#, c-format
+msgid "Only show deleted instances"
+msgstr ""
+
+#: src/paths/admin/list/View.tsx:81
+#, c-format
+msgid "Deleted"
+msgstr ""
+
+#: src/paths/admin/list/View.tsx:88
+#, c-format
+msgid "Show all instances"
+msgstr ""
+
+#: src/paths/admin/list/View.tsx:91
+#, c-format
+msgid "All"
+msgstr ""
+
+#: src/paths/admin/list/index.tsx:101
+#, c-format
+msgid "Instance \"%1$s\" (ID: %2$s) has been deleted"
+msgstr ""
+
+#: src/paths/admin/list/index.tsx:106
+#, c-format
+msgid "Failed to delete instance"
+msgstr ""
+
+#: src/paths/admin/list/index.tsx:124
+#, c-format
+msgid "Instance '%1$s' (ID: %2$s) has been disabled"
+msgstr ""
+
+#: src/paths/admin/list/index.tsx:129
+#, c-format
+msgid "Failed to purge instance"
+msgstr ""
+
+#: src/paths/instance/kyc/list/ListPage.tsx:41
+#, c-format
+msgid "Pending KYC verification"
+msgstr ""
+
+#: src/paths/instance/kyc/list/ListPage.tsx:66
+#, c-format
+msgid "Timed out"
+msgstr ""
+
+#: src/paths/instance/kyc/list/ListPage.tsx:103
+#, c-format
+msgid "Exchange"
+msgstr ""
+
+#: src/paths/instance/kyc/list/ListPage.tsx:106
+#, c-format
+msgid "Target account"
+msgstr ""
+
+#: src/paths/instance/kyc/list/ListPage.tsx:109
+#, c-format
+msgid "KYC URL"
+msgstr ""
+
+#: src/paths/instance/kyc/list/ListPage.tsx:144
+#, c-format
+msgid "Code"
+msgstr ""
+
+#: src/paths/instance/kyc/list/ListPage.tsx:147
+#, c-format
+msgid "Http Status"
+msgstr ""
+
+#: src/paths/instance/kyc/list/ListPage.tsx:177
+#, c-format
+msgid "No pending kyc verification!"
+msgstr ""
+
+#: src/components/form/InputDate.tsx:123
+#, c-format
+msgid "change value to unknown date"
+msgstr ""
+
+#: src/components/form/InputDate.tsx:124
+#, c-format
+msgid "change value to empty"
+msgstr ""
+
+#: src/components/form/InputDate.tsx:131
+#, c-format
+msgid "clear"
+msgstr ""
+
+#: src/components/form/InputDate.tsx:136
+#, c-format
+msgid "change value to never"
+msgstr ""
+
+#: src/components/form/InputDate.tsx:141
+#, c-format
+msgid "never"
+msgstr ""
+
+#: src/components/form/InputLocation.tsx:29
+#, c-format
+msgid "Country"
+msgstr ""
+
+#: src/components/form/InputLocation.tsx:33
+#, c-format
+msgid "Address"
+msgstr ""
+
+#: src/components/form/InputLocation.tsx:39
+#, c-format
+msgid "Building number"
+msgstr ""
+
+#: src/components/form/InputLocation.tsx:41
+#, c-format
+msgid "Building name"
+msgstr ""
+
+#: src/components/form/InputLocation.tsx:42
+#, c-format
+msgid "Street"
+msgstr ""
+
+#: src/components/form/InputLocation.tsx:43
+#, c-format
+msgid "Post code"
+msgstr ""
+
+#: src/components/form/InputLocation.tsx:44
+#, c-format
+msgid "Town location"
+msgstr ""
+
+#: src/components/form/InputLocation.tsx:45
+#, c-format
+msgid "Town"
+msgstr ""
+
+#: src/components/form/InputLocation.tsx:46
+#, c-format
+msgid "District"
+msgstr ""
+
+#: src/components/form/InputLocation.tsx:49
+#, c-format
+msgid "Country subdivision"
+msgstr ""
+
+#: src/components/form/InputSearchProduct.tsx:66
+#, c-format
+msgid "Product id"
+msgstr ""
+
+#: src/components/form/InputSearchProduct.tsx:69
+#, c-format
+msgid "Description"
+msgstr ""
+
+#: src/components/form/InputSearchProduct.tsx:94
+#, c-format
+msgid "Product"
+msgstr ""
+
+#: src/components/form/InputSearchProduct.tsx:95
+#, c-format
+msgid "search products by it's description or id"
+msgstr ""
+
+#: src/components/form/InputSearchProduct.tsx:151
+#, c-format
+msgid "no products found with that description"
+msgstr ""
+
+#: src/components/product/InventoryProductForm.tsx:56
+#, c-format
+msgid "You must enter a valid product identifier."
+msgstr ""
+
+#: src/components/product/InventoryProductForm.tsx:64
+#, c-format
+msgid "Quantity must be greater than 0!"
+msgstr ""
+
+#: src/components/product/InventoryProductForm.tsx:76
+#, c-format
+msgid ""
+"This quantity exceeds remaining stock. Currently, only %1$s units remain "
+"unreserved in stock."
+msgstr ""
+
+#: src/components/product/InventoryProductForm.tsx:109
+#, c-format
+msgid "Quantity"
+msgstr ""
+
+#: src/components/product/InventoryProductForm.tsx:110
+#, c-format
+msgid "how many products will be added"
+msgstr ""
+
+#: src/components/product/InventoryProductForm.tsx:117
+#, c-format
+msgid "Add from inventory"
+msgstr ""
+
+#: src/components/form/InputImage.tsx:105
+#, c-format
+msgid "Image should be smaller than 1 MB"
+msgstr ""
+
+#: src/components/form/InputImage.tsx:110
+#, c-format
+msgid "Add"
+msgstr ""
+
+#: src/components/form/InputImage.tsx:115
+#, c-format
+msgid "Remove"
+msgstr ""
+
+#: src/components/form/InputTaxes.tsx:113
+#, c-format
+msgid "No taxes configured for this product."
+msgstr ""
+
+#: src/components/form/InputTaxes.tsx:119
+#, c-format
+msgid "Amount"
+msgstr "Importo"
+
+#: src/components/form/InputTaxes.tsx:120
+#, c-format
+msgid ""
+"Taxes can be in currencies that differ from the main currency used by the "
+"merchant."
+msgstr ""
+
+#: src/components/form/InputTaxes.tsx:122
+#, c-format
+msgid ""
+"Enter currency and value separated with a colon, e.g. &quot;USD:2.3&quot;."
+msgstr ""
+
+#: src/components/form/InputTaxes.tsx:131
+#, c-format
+msgid "Legal name of the tax, e.g. VAT or import duties."
+msgstr ""
+
+#: src/components/form/InputTaxes.tsx:137
+#, c-format
+msgid "add tax to the tax list"
+msgstr ""
+
+#: src/components/product/NonInventoryProductForm.tsx:72
+#, c-format
+msgid "describe and add a product that is not in the inventory list"
+msgstr ""
+
+#: src/components/product/NonInventoryProductForm.tsx:75
+#, c-format
+msgid "Add custom product"
+msgstr ""
+
+#: src/components/product/NonInventoryProductForm.tsx:86
+#, c-format
+msgid "Complete information of the product"
+msgstr ""
+
+#: src/components/product/NonInventoryProductForm.tsx:185
+#, c-format
+msgid "Image"
+msgstr ""
+
+#: src/components/product/NonInventoryProductForm.tsx:186
+#, c-format
+msgid "photo of the product"
+msgstr ""
+
+#: src/components/product/NonInventoryProductForm.tsx:192
+#, c-format
+msgid "full product description"
+msgstr ""
+
+#: src/components/product/NonInventoryProductForm.tsx:196
+#, c-format
+msgid "Unit"
+msgstr ""
+
+#: src/components/product/NonInventoryProductForm.tsx:197
+#, c-format
+msgid "name of the product unit"
+msgstr ""
+
+#: src/components/product/NonInventoryProductForm.tsx:201
+#, c-format
+msgid "Price"
+msgstr ""
+
+#: src/components/product/NonInventoryProductForm.tsx:202
+#, c-format
+msgid "amount in the current currency"
+msgstr ""
+
+#: src/components/product/NonInventoryProductForm.tsx:211
+#, c-format
+msgid "Taxes"
+msgstr ""
+
+#: src/components/product/ProductList.tsx:38
+#, c-format
+msgid "image"
+msgstr ""
+
+#: src/components/product/ProductList.tsx:41
+#, c-format
+msgid "description"
+msgstr ""
+
+#: src/components/product/ProductList.tsx:44
+#, c-format
+msgid "quantity"
+msgstr ""
+
+#: src/components/product/ProductList.tsx:47
+#, c-format
+msgid "unit price"
+msgstr ""
+
+#: src/components/product/ProductList.tsx:50
+#, c-format
+msgid "total price"
+msgstr ""
+
+#: src/paths/instance/orders/create/CreatePage.tsx:153
+#, c-format
+msgid "required"
+msgstr ""
+
+#: src/paths/instance/orders/create/CreatePage.tsx:157
+#, c-format
+msgid "not valid"
+msgstr ""
+
+#: src/paths/instance/orders/create/CreatePage.tsx:159
+#, c-format
+msgid "must be greater than 0"
+msgstr ""
+
+#: src/paths/instance/orders/create/CreatePage.tsx:164
+#, c-format
+msgid "not a valid json"
+msgstr ""
+
+#: src/paths/instance/orders/create/CreatePage.tsx:170
+#, c-format
+msgid "should be in the future"
+msgstr ""
+
+#: src/paths/instance/orders/create/CreatePage.tsx:173
+#, c-format
+msgid "refund deadline cannot be before pay deadline"
+msgstr ""
+
+#: src/paths/instance/orders/create/CreatePage.tsx:179
+#, c-format
+msgid "wire transfer deadline cannot be before refund deadline"
+msgstr ""
+
+#: src/paths/instance/orders/create/CreatePage.tsx:190
+#, c-format
+msgid "wire transfer deadline cannot be before pay deadline"
+msgstr ""
+
+#: src/paths/instance/orders/create/CreatePage.tsx:197
+#, c-format
+msgid "should have a refund deadline"
+msgstr ""
+
+#: src/paths/instance/orders/create/CreatePage.tsx:202
+#, c-format
+msgid "auto refund cannot be after refund deadline"
+msgstr ""
+
+#: src/paths/instance/orders/create/CreatePage.tsx:360
+#, c-format
+msgid "Manage products in order"
+msgstr ""
+
+#: src/paths/instance/orders/create/CreatePage.tsx:369
+#, c-format
+msgid "Manage list of products in the order."
+msgstr ""
+
+#: src/paths/instance/orders/create/CreatePage.tsx:391
+#, c-format
+msgid "Remove this product from the order."
+msgstr ""
+
+#: src/paths/instance/orders/create/CreatePage.tsx:415
+#, c-format
+msgid "Total price"
+msgstr ""
+
+#: src/paths/instance/orders/create/CreatePage.tsx:417
+#, c-format
+msgid "total product price added up"
+msgstr ""
+
+#: src/paths/instance/orders/create/CreatePage.tsx:430
+#, c-format
+msgid "Amount to be paid by the customer"
+msgstr ""
+
+#: src/paths/instance/orders/create/CreatePage.tsx:436
+#, c-format
+msgid "Order price"
+msgstr ""
+
+#: src/paths/instance/orders/create/CreatePage.tsx:437
+#, c-format
+msgid "final order price"
+msgstr ""
+
+#: src/paths/instance/orders/create/CreatePage.tsx:444
+#, c-format
+msgid "Summary"
+msgstr ""
+
+#: src/paths/instance/orders/create/CreatePage.tsx:445
+#, c-format
+msgid "Title of the order to be shown to the customer"
+msgstr ""
+
+#: src/paths/instance/orders/create/CreatePage.tsx:450
+#, c-format
+msgid "Shipping and Fulfillment"
+msgstr ""
+
+#: src/paths/instance/orders/create/CreatePage.tsx:455
+#, c-format
+msgid "Delivery date"
+msgstr ""
+
+#: src/paths/instance/orders/create/CreatePage.tsx:456
+#, c-format
+msgid "Deadline for physical delivery assured by the merchant."
+msgstr ""
+
+#: src/paths/instance/orders/create/CreatePage.tsx:461
+#, c-format
+msgid "Location"
+msgstr ""
+
+#: src/paths/instance/orders/create/CreatePage.tsx:462
+#, c-format
+msgid "address where the products will be delivered"
+msgstr ""
+
+#: src/paths/instance/orders/create/CreatePage.tsx:469
+#, c-format
+msgid "Fulfillment URL"
+msgstr ""
+
+#: src/paths/instance/orders/create/CreatePage.tsx:470
+#, c-format
+msgid "URL to which the user will be redirected after successful payment."
+msgstr ""
+
+#: src/paths/instance/orders/create/CreatePage.tsx:476
+#, c-format
+msgid "Taler payment options"
+msgstr ""
+
+#: src/paths/instance/orders/create/CreatePage.tsx:477
+#, c-format
+msgid "Override default Taler payment settings for this order"
+msgstr ""
+
+#: src/paths/instance/orders/create/CreatePage.tsx:481
+#, c-format
+msgid "Payment deadline"
+msgstr ""
+
+#: src/paths/instance/orders/create/CreatePage.tsx:482
+#, c-format
+msgid ""
+"Deadline for the customer to pay for the offer before it expires. Inventory "
+"products will be reserved until this deadline."
+msgstr ""
+
+#: src/paths/instance/orders/create/CreatePage.tsx:486
+#, c-format
+msgid "Refund deadline"
+msgstr ""
+
+#: src/paths/instance/orders/create/CreatePage.tsx:487
+#, c-format
+msgid "Time until which the order can be refunded by the merchant."
+msgstr ""
+
+#: src/paths/instance/orders/create/CreatePage.tsx:491
+#, c-format
+msgid "Wire transfer deadline"
+msgstr ""
+
+#: src/paths/instance/orders/create/CreatePage.tsx:492
+#, c-format
+msgid "Deadline for the exchange to make the wire transfer."
+msgstr ""
+
+#: src/paths/instance/orders/create/CreatePage.tsx:496
+#, c-format
+msgid "Auto-refund deadline"
+msgstr ""
+
+#: src/paths/instance/orders/create/CreatePage.tsx:497
+#, c-format
+msgid ""
+"Time until which the wallet will automatically check for refunds without "
+"user interaction."
+msgstr ""
+
+#: src/paths/instance/orders/create/CreatePage.tsx:502
+#, c-format
+msgid "Maximum deposit fee"
+msgstr ""
+
+#: src/paths/instance/orders/create/CreatePage.tsx:503
+#, c-format
+msgid ""
+"Maximum deposit fees the merchant is willing to cover for this order. Higher "
+"deposit fees must be covered in full by the consumer."
+msgstr ""
+
+#: src/paths/instance/orders/create/CreatePage.tsx:507
+#, c-format
+msgid "Maximum wire fee"
+msgstr ""
+
+#: src/paths/instance/orders/create/CreatePage.tsx:508
+#, c-format
+msgid ""
+"Maximum aggregate wire fees the merchant is willing to cover for this order. "
+"Wire fees exceeding this amount are to be covered by the customers."
+msgstr ""
+
+#: src/paths/instance/orders/create/CreatePage.tsx:512
+#, c-format
+msgid "Wire fee amortization"
+msgstr ""
+
+#: src/paths/instance/orders/create/CreatePage.tsx:513
+#, c-format
+msgid ""
+"Factor by which wire fees exceeding the above threshold are divided to "
+"determine the share of excess wire fees to be paid explicitly by the "
+"consumer."
+msgstr ""
+
+#: src/paths/instance/orders/create/CreatePage.tsx:517
+#, c-format
+msgid "Create token"
+msgstr ""
+
+#: src/paths/instance/orders/create/CreatePage.tsx:518
+#, c-format
+msgid ""
+"Uncheck this option if the merchant backend generated an order ID with "
+"enough entropy to prevent adversarial claims."
+msgstr ""
+
+#: src/paths/instance/orders/create/CreatePage.tsx:522
+#, c-format
+msgid "Minimum age required"
+msgstr ""
+
+#: src/paths/instance/orders/create/CreatePage.tsx:523
+#, c-format
+msgid ""
+"Any value greater than 0 will limit the coins able be used to pay this "
+"contract. If empty the age restriction will be defined by the products"
+msgstr ""
+
+#: src/paths/instance/orders/create/CreatePage.tsx:526
+#, c-format
+msgid "Min age defined by the producs is %1$s"
+msgstr ""
+
+#: src/paths/instance/orders/create/CreatePage.tsx:534
+#, c-format
+msgid "Additional information"
+msgstr ""
+
+#: src/paths/instance/orders/create/CreatePage.tsx:535
+#, c-format
+msgid "Custom information to be included in the contract for this order."
+msgstr ""
+
+#: src/paths/instance/orders/create/CreatePage.tsx:541
+#, c-format
+msgid "You must enter a value in JavaScript Object Notation (JSON)."
+msgstr ""
+
+#: src/components/picker/DurationPicker.tsx:55
+#, c-format
+msgid "days"
+msgstr ""
+
+#: src/components/picker/DurationPicker.tsx:65
+#, c-format
+msgid "hours"
+msgstr ""
+
+#: src/components/picker/DurationPicker.tsx:76
+#, c-format
+msgid "minutes"
+msgstr ""
+
+#: src/components/picker/DurationPicker.tsx:87
+#, c-format
+msgid "seconds"
+msgstr ""
+
+#: src/components/form/InputDuration.tsx:53
+#, c-format
+msgid "forever"
+msgstr ""
+
+#: src/components/form/InputDuration.tsx:62
+#, c-format
+msgid "%1$sM"
+msgstr ""
+
+#: src/components/form/InputDuration.tsx:64
+#, c-format
+msgid "%1$sY"
+msgstr ""
+
+#: src/components/form/InputDuration.tsx:66
+#, c-format
+msgid "%1$sd"
+msgstr ""
+
+#: src/components/form/InputDuration.tsx:68
+#, c-format
+msgid "%1$sh"
+msgstr ""
+
+#: src/components/form/InputDuration.tsx:70
+#, c-format
+msgid "%1$smin"
+msgstr ""
+
+#: src/components/form/InputDuration.tsx:72
+#, c-format
+msgid "%1$ssec"
+msgstr ""
+
+#: src/paths/instance/orders/list/Table.tsx:75
+#, c-format
+msgid "Orders"
+msgstr ""
+
+#: src/paths/instance/orders/list/Table.tsx:81
+#, c-format
+msgid "create order"
+msgstr ""
+
+#: src/paths/instance/orders/list/Table.tsx:147
+#, c-format
+msgid "load newer orders"
+msgstr ""
+
+#: src/paths/instance/orders/list/Table.tsx:154
+#, c-format
+msgid "Date"
+msgstr "Data"
+
+#: src/paths/instance/orders/list/Table.tsx:200
+#, c-format
+msgid "Refund"
+msgstr ""
+
+#: src/paths/instance/orders/list/Table.tsx:209
+#, c-format
+msgid "copy url"
+msgstr ""
+
+#: src/paths/instance/orders/list/Table.tsx:225
+#, c-format
+msgid "load older orders"
+msgstr ""
+
+#: src/paths/instance/orders/list/Table.tsx:242
+#, c-format
+msgid "No orders have been found matching your query!"
+msgstr ""
+
+#: src/paths/instance/orders/list/Table.tsx:288
+#, c-format
+msgid "duplicated"
+msgstr ""
+
+#: src/paths/instance/orders/list/Table.tsx:299
+#, c-format
+msgid "invalid format"
+msgstr ""
+
+#: src/paths/instance/orders/list/Table.tsx:301
+#, c-format
+msgid "this value exceed the refundable amount"
+msgstr ""
+
+#: src/paths/instance/orders/list/Table.tsx:346
+#, c-format
+msgid "date"
+msgstr ""
+
+#: src/paths/instance/orders/list/Table.tsx:349
+#, c-format
+msgid "amount"
+msgstr ""
+
+#: src/paths/instance/orders/list/Table.tsx:352
+#, c-format
+msgid "reason"
+msgstr ""
+
+#: src/paths/instance/orders/list/Table.tsx:389
+#, c-format
+msgid "amount to be refunded"
+msgstr ""
+
+#: src/paths/instance/orders/list/Table.tsx:391
+#, c-format
+msgid "Max refundable:"
+msgstr ""
+
+#: src/paths/instance/orders/list/Table.tsx:396
+#, c-format
+msgid "Reason"
+msgstr ""
+
+#: src/paths/instance/orders/list/Table.tsx:397
+#, c-format
+msgid "Choose one..."
+msgstr ""
+
+#: src/paths/instance/orders/list/Table.tsx:399
+#, c-format
+msgid "requested by the customer"
+msgstr ""
+
+#: src/paths/instance/orders/list/Table.tsx:400
+#, c-format
+msgid "other"
+msgstr ""
+
+#: src/paths/instance/orders/list/Table.tsx:403
+#, c-format
+msgid "why this order is being refunded"
+msgstr ""
+
+#: src/paths/instance/orders/list/Table.tsx:409
+#, c-format
+msgid "more information to give context"
+msgstr ""
+
+#: src/paths/instance/orders/details/DetailPage.tsx:62
+#, c-format
+msgid "Contract Terms"
+msgstr ""
+
+#: src/paths/instance/orders/details/DetailPage.tsx:68
+#, c-format
+msgid "human-readable description of the whole purchase"
+msgstr ""
+
+#: src/paths/instance/orders/details/DetailPage.tsx:74
+#, c-format
+msgid "total price for the transaction"
+msgstr ""
+
+#: src/paths/instance/orders/details/DetailPage.tsx:81
+#, c-format
+msgid "URL for this purchase"
+msgstr ""
+
+#: src/paths/instance/orders/details/DetailPage.tsx:87
+#, c-format
+msgid "Max fee"
+msgstr ""
+
+#: src/paths/instance/orders/details/DetailPage.tsx:88
+#, c-format
+msgid "maximum total deposit fee accepted by the merchant for this contract"
+msgstr ""
+
+#: src/paths/instance/orders/details/DetailPage.tsx:93
+#, c-format
+msgid "Max wire fee"
+msgstr ""
+
+#: src/paths/instance/orders/details/DetailPage.tsx:94
+#, c-format
+msgid "maximum wire fee accepted by the merchant"
+msgstr ""
+
+#: src/paths/instance/orders/details/DetailPage.tsx:100
+#, c-format
+msgid ""
+"over how many customer transactions does the merchant expect to amortize "
+"wire fees on average"
+msgstr ""
+
+#: src/paths/instance/orders/details/DetailPage.tsx:105
+#, c-format
+msgid "Created at"
+msgstr ""
+
+#: src/paths/instance/orders/details/DetailPage.tsx:106
+#, c-format
+msgid "time when this contract was generated"
+msgstr ""
+
+#: src/paths/instance/orders/details/DetailPage.tsx:112
+#, c-format
+msgid "after this deadline has passed no refunds will be accepted"
+msgstr ""
+
+#: src/paths/instance/orders/details/DetailPage.tsx:118
+#, c-format
+msgid ""
+"after this deadline, the merchant won't accept payments for the contract"
+msgstr ""
+
+#: src/paths/instance/orders/details/DetailPage.tsx:124
+#, c-format
+msgid "transfer deadline for the exchange"
+msgstr ""
+
+#: src/paths/instance/orders/details/DetailPage.tsx:130
+#, c-format
+msgid "time indicating when the order should be delivered"
+msgstr ""
+
+#: src/paths/instance/orders/details/DetailPage.tsx:136
+#, c-format
+msgid "where the order will be delivered"
+msgstr ""
+
+#: src/paths/instance/orders/details/DetailPage.tsx:144
+#, c-format
+msgid "Auto-refund delay"
+msgstr ""
+
+#: src/paths/instance/orders/details/DetailPage.tsx:145
+#, c-format
+msgid ""
+"how long the wallet should try to get an automatic refund for the purchase"
+msgstr ""
+
+#: src/paths/instance/orders/details/DetailPage.tsx:150
+#, c-format
+msgid "Extra info"
+msgstr ""
+
+#: src/paths/instance/orders/details/DetailPage.tsx:151
+#, c-format
+msgid "extra data that is only interpreted by the merchant frontend"
+msgstr ""
+
+#: src/paths/instance/orders/details/DetailPage.tsx:219
+#, c-format
+msgid "Order"
+msgstr ""
+
+#: src/paths/instance/orders/details/DetailPage.tsx:221
+#, c-format
+msgid "claimed"
+msgstr ""
+
+#: src/paths/instance/orders/details/DetailPage.tsx:247
+#, c-format
+msgid "claimed at"
+msgstr ""
+
+#: src/paths/instance/orders/details/DetailPage.tsx:265
+#, c-format
+msgid "Timeline"
+msgstr ""
+
+#: src/paths/instance/orders/details/DetailPage.tsx:271
+#, c-format
+msgid "Payment details"
+msgstr ""
+
+#: src/paths/instance/orders/details/DetailPage.tsx:291
+#, c-format
+msgid "Order status"
+msgstr ""
+
+#: src/paths/instance/orders/details/DetailPage.tsx:301
+#, c-format
+msgid "Product list"
+msgstr ""
+
+#: src/paths/instance/orders/details/DetailPage.tsx:451
+#, c-format
+msgid "paid"
+msgstr ""
+
+#: src/paths/instance/orders/details/DetailPage.tsx:455
+#, c-format
+msgid "wired"
+msgstr ""
+
+#: src/paths/instance/orders/details/DetailPage.tsx:460
+#, c-format
+msgid "refunded"
+msgstr ""
+
+#: src/paths/instance/orders/details/DetailPage.tsx:480
+#, c-format
+msgid "refund order"
+msgstr ""
+
+#: src/paths/instance/orders/details/DetailPage.tsx:481
+#, c-format
+msgid "not refundable"
+msgstr ""
+
+#: src/paths/instance/orders/details/DetailPage.tsx:489
+#, c-format
+msgid "refund"
+msgstr ""
+
+#: src/paths/instance/orders/details/DetailPage.tsx:553
+#, c-format
+msgid "Refunded amount"
+msgstr ""
+
+#: src/paths/instance/orders/details/DetailPage.tsx:560
+#, c-format
+msgid "Refund taken"
+msgstr ""
+
+#: src/paths/instance/orders/details/DetailPage.tsx:570
+#, c-format
+msgid "Status URL"
+msgstr ""
+
+#: src/paths/instance/orders/details/DetailPage.tsx:583
+#, c-format
+msgid "Refund URI"
+msgstr ""
+
+#: src/paths/instance/orders/details/DetailPage.tsx:636
+#, c-format
+msgid "unpaid"
+msgstr ""
+
+#: src/paths/instance/orders/details/DetailPage.tsx:654
+#, c-format
+msgid "pay at"
+msgstr ""
+
+#: src/paths/instance/orders/details/DetailPage.tsx:666
+#, c-format
+msgid "created at"
+msgstr ""
+
+#: src/paths/instance/orders/details/DetailPage.tsx:707
+#, c-format
+msgid "Order status URL"
+msgstr ""
+
+#: src/paths/instance/orders/details/DetailPage.tsx:711
+#, c-format
+msgid "Payment URI"
+msgstr ""
+
+#: src/paths/instance/orders/details/DetailPage.tsx:740
+#, c-format
+msgid ""
+"Unknown order status. This is an error, please contact the administrator."
+msgstr ""
+
+#: src/paths/instance/orders/details/DetailPage.tsx:767
+#, c-format
+msgid "Back"
+msgstr "Indietro"
+
+#: src/paths/instance/orders/details/index.tsx:79
+#, c-format
+msgid "refund created successfully"
+msgstr ""
+
+#: src/paths/instance/orders/details/index.tsx:85
+#, c-format
+msgid "could not create the refund"
+msgstr ""
+
+#: src/paths/instance/orders/list/ListPage.tsx:78
+#, c-format
+msgid "select date to show nearby orders"
+msgstr ""
+
+#: src/paths/instance/orders/list/ListPage.tsx:94
+#, c-format
+msgid "order id"
+msgstr ""
+
+#: src/paths/instance/orders/list/ListPage.tsx:100
+#, c-format
+msgid "jump to order with the given order ID"
+msgstr ""
+
+#: src/paths/instance/orders/list/ListPage.tsx:122
+#, c-format
+msgid "remove all filters"
+msgstr ""
+
+#: src/paths/instance/orders/list/ListPage.tsx:132
+#, c-format
+msgid "only show paid orders"
+msgstr ""
+
+#: src/paths/instance/orders/list/ListPage.tsx:135
+#, c-format
+msgid "Paid"
+msgstr ""
+
+#: src/paths/instance/orders/list/ListPage.tsx:142
+#, c-format
+msgid "only show orders with refunds"
+msgstr ""
+
+#: src/paths/instance/orders/list/ListPage.tsx:145
+#, c-format
+msgid "Refunded"
+msgstr "Rimborsato"
+
+#: src/paths/instance/orders/list/ListPage.tsx:152
+#, c-format
+msgid ""
+"only show orders where customers paid, but wire payments from payment "
+"provider are still pending"
+msgstr ""
+
+#: src/paths/instance/orders/list/ListPage.tsx:155
+#, c-format
+msgid "Not wired"
+msgstr ""
+
+#: src/paths/instance/orders/list/ListPage.tsx:170
+#, c-format
+msgid "clear date filter"
+msgstr ""
+
+#: src/paths/instance/orders/list/ListPage.tsx:184
+#, c-format
+msgid "date (YYYY/MM/DD)"
+msgstr ""
+
+#: src/paths/instance/orders/list/index.tsx:103
+#, c-format
+msgid "Enter an order id"
+msgstr ""
+
+#: src/paths/instance/orders/list/index.tsx:111
+#, c-format
+msgid "order not found"
+msgstr ""
+
+#: src/paths/instance/orders/list/index.tsx:178
+#, c-format
+msgid "could not get the order to refund"
+msgstr ""
+
+#: src/components/exception/AsyncButton.tsx:43
+#, c-format
+msgid "Loading..."
+msgstr ""
+
+#: src/components/form/InputStock.tsx:99
+#, c-format
+msgid ""
+"click here to configure the stock of the product, leave it as is and the "
+"backend will not control stock"
+msgstr ""
+
+#: src/components/form/InputStock.tsx:109
+#, c-format
+msgid "Manage stock"
+msgstr ""
+
+#: src/components/form/InputStock.tsx:115
+#, c-format
+msgid "this product has been configured without stock control"
+msgstr ""
+
+#: src/components/form/InputStock.tsx:119
+#, c-format
+msgid "Infinite"
+msgstr ""
+
+#: src/components/form/InputStock.tsx:136
+#, c-format
+msgid "lost cannot be greater than current and incoming (max %1$s)"
+msgstr ""
+
+#: src/components/form/InputStock.tsx:176
+#, c-format
+msgid "Incoming"
+msgstr ""
+
+#: src/components/form/InputStock.tsx:177
+#, c-format
+msgid "Lost"
+msgstr ""
+
+#: src/components/form/InputStock.tsx:192
+#, c-format
+msgid "Current"
+msgstr ""
+
+#: src/components/form/InputStock.tsx:196
+#, c-format
+msgid "remove stock control for this product"
+msgstr ""
+
+#: src/components/form/InputStock.tsx:202
+#, c-format
+msgid "without stock"
+msgstr ""
+
+#: src/components/form/InputStock.tsx:211
+#, c-format
+msgid "Next restock"
+msgstr ""
+
+#: src/components/form/InputStock.tsx:217
+#, c-format
+msgid "Delivery address"
+msgstr ""
+
+#: src/components/product/ProductForm.tsx:133
+#, c-format
+msgid "product identification to use in URLs (for internal use only)"
+msgstr ""
+
+#: src/components/product/ProductForm.tsx:139
+#, c-format
+msgid "illustration of the product for customers"
+msgstr ""
+
+#: src/components/product/ProductForm.tsx:145
+#, c-format
+msgid "product description for customers"
+msgstr ""
+
+#: src/components/product/ProductForm.tsx:149
+#, c-format
+msgid "Age restricted"
+msgstr ""
+
+#: src/components/product/ProductForm.tsx:150
+#, c-format
+msgid "is this product restricted for customer below certain age?"
+msgstr ""
+
+#: src/components/product/ProductForm.tsx:155
+#, c-format
+msgid ""
+"unit describing quantity of product sold (e.g. 2 kilograms, 5 liters, 3 "
+"items, 5 meters) for customers"
+msgstr ""
+
+#: src/components/product/ProductForm.tsx:160
+#, c-format
+msgid ""
+"sale price for customers, including taxes, for above units of the product"
+msgstr ""
+
+#: src/components/product/ProductForm.tsx:164
+#, c-format
+msgid "Stock"
+msgstr ""
+
+#: src/components/product/ProductForm.tsx:166
+#, c-format
+msgid ""
+"product inventory for products with finite supply (for internal use only)"
+msgstr ""
+
+#: src/components/product/ProductForm.tsx:171
+#, c-format
+msgid "taxes included in the product price, exposed to customers"
+msgstr ""
+
+#: src/paths/instance/products/create/CreatePage.tsx:66
+#, c-format
+msgid "Need to complete marked fields"
+msgstr ""
+
+#: src/paths/instance/products/create/index.tsx:51
+#, c-format
+msgid "could not create product"
+msgstr ""
+
+#: src/paths/instance/products/list/Table.tsx:68
+#, c-format
+msgid "Products"
+msgstr ""
+
+#: src/paths/instance/products/list/Table.tsx:73
+#, c-format
+msgid "add product to inventory"
+msgstr ""
+
+#: src/paths/instance/products/list/Table.tsx:137
+#, c-format
+msgid "Sell"
+msgstr ""
+
+#: src/paths/instance/products/list/Table.tsx:143
+#, c-format
+msgid "Profit"
+msgstr ""
+
+#: src/paths/instance/products/list/Table.tsx:149
+#, c-format
+msgid "Sold"
+msgstr ""
+
+#: src/paths/instance/products/list/Table.tsx:210
+#, c-format
+msgid "free"
+msgstr ""
+
+#: src/paths/instance/products/list/Table.tsx:248
+#, c-format
+msgid "go to product update page"
+msgstr ""
+
+#: src/paths/instance/products/list/Table.tsx:255
+#, c-format
+msgid "Update"
+msgstr ""
+
+#: src/paths/instance/products/list/Table.tsx:260
+#, c-format
+msgid "remove this product from the database"
+msgstr ""
+
+#: src/paths/instance/products/list/Table.tsx:331
+#, c-format
+msgid "update the product with new price"
+msgstr ""
+
+#: src/paths/instance/products/list/Table.tsx:341
+#, c-format
+msgid "update product with new price"
+msgstr ""
+
+#: src/paths/instance/products/list/Table.tsx:399
+#, c-format
+msgid "add more elements to the inventory"
+msgstr ""
+
+#: src/paths/instance/products/list/Table.tsx:404
+#, c-format
+msgid "report elements lost in the inventory"
+msgstr ""
+
+#: src/paths/instance/products/list/Table.tsx:409
+#, c-format
+msgid "new price for the product"
+msgstr ""
+
+#: src/paths/instance/products/list/Table.tsx:421
+#, c-format
+msgid "the are value with errors"
+msgstr ""
+
+#: src/paths/instance/products/list/Table.tsx:422
+#, c-format
+msgid "update product with new stock and price"
+msgstr ""
+
+#: src/paths/instance/products/list/Table.tsx:463
+#, c-format
+msgid "There is no products yet, add more pressing the + sign"
+msgstr ""
+
+#: src/paths/instance/products/list/index.tsx:86
+#, c-format
+msgid "product updated successfully"
+msgstr ""
+
+#: src/paths/instance/products/list/index.tsx:92
+#, c-format
+msgid "could not update the product"
+msgstr ""
+
+#: src/paths/instance/products/list/index.tsx:103
+#, c-format
+msgid "product delete successfully"
+msgstr ""
+
+#: src/paths/instance/products/list/index.tsx:109
+#, c-format
+msgid "could not delete the product"
+msgstr ""
+
+#: src/paths/instance/products/update/UpdatePage.tsx:56
+#, c-format
+msgid "Product id:"
+msgstr ""
+
+#: src/paths/instance/reserves/create/CreatedSuccessfully.tsx:95
+#, c-format
+msgid ""
+"To complete the setup of the reserve, you must now initiate a wire transfer "
+"using the given wire transfer subject and crediting the specified amount to "
+"the indicated account of the exchange."
+msgstr ""
+
+#: src/paths/instance/reserves/create/CreatedSuccessfully.tsx:102
+#, c-format
+msgid "If your system supports RFC 8905, you can do this by opening this URI:"
+msgstr ""
+
+#: src/paths/instance/reserves/create/CreatePage.tsx:83
+#, c-format
+msgid "it should be greater than 0"
+msgstr ""
+
+#: src/paths/instance/reserves/create/CreatePage.tsx:88
+#, c-format
+msgid "must be a valid URL"
+msgstr ""
+
+#: src/paths/instance/reserves/create/CreatePage.tsx:107
+#, c-format
+msgid "Initial balance"
+msgstr ""
+
+#: src/paths/instance/reserves/create/CreatePage.tsx:108
+#, c-format
+msgid "balance prior to deposit"
+msgstr ""
+
+#: src/paths/instance/reserves/create/CreatePage.tsx:112
+#, c-format
+msgid "Exchange URL"
+msgstr ""
+
+#: src/paths/instance/reserves/create/CreatePage.tsx:113
+#, c-format
+msgid "URL of exchange"
+msgstr ""
+
+#: src/paths/instance/reserves/create/CreatePage.tsx:148
+#, c-format
+msgid "Next"
+msgstr ""
+
+#: src/paths/instance/reserves/create/CreatePage.tsx:186
+#, c-format
+msgid "Wire method"
+msgstr ""
+
+#: src/paths/instance/reserves/create/CreatePage.tsx:187
+#, c-format
+msgid "method to use for wire transfer"
+msgstr ""
+
+#: src/paths/instance/reserves/create/CreatePage.tsx:189
+#, c-format
+msgid "Select one wire method"
+msgstr ""
+
+#: src/paths/instance/reserves/create/index.tsx:62
+#, c-format
+msgid "could not create reserve"
+msgstr ""
+
+#: src/paths/instance/reserves/details/DetailPage.tsx:77
+#, c-format
+msgid "Valid until"
+msgstr ""
+
+#: src/paths/instance/reserves/details/DetailPage.tsx:82
+#, c-format
+msgid "Created balance"
+msgstr ""
+
+#: src/paths/instance/reserves/details/DetailPage.tsx:99
+#, c-format
+msgid "Exchange balance"
+msgstr ""
+
+#: src/paths/instance/reserves/details/DetailPage.tsx:104
+#, c-format
+msgid "Picked up"
+msgstr ""
+
+#: src/paths/instance/reserves/details/DetailPage.tsx:109
+#, c-format
+msgid "Committed"
+msgstr ""
+
+#: src/paths/instance/reserves/details/DetailPage.tsx:116
+#, c-format
+msgid "Account address"
+msgstr ""
+
+#: src/paths/instance/reserves/details/DetailPage.tsx:119
+#, c-format
+msgid "Subject"
+msgstr "Soggetto"
+
+#: src/paths/instance/reserves/details/DetailPage.tsx:130
+#, c-format
+msgid "Tips"
+msgstr ""
+
+#: src/paths/instance/reserves/details/DetailPage.tsx:193
+#, c-format
+msgid "No tips has been authorized from this reserve"
+msgstr ""
+
+#: src/paths/instance/reserves/details/DetailPage.tsx:213
+#, c-format
+msgid "Authorized"
+msgstr ""
+
+#: src/paths/instance/reserves/details/DetailPage.tsx:222
+#, c-format
+msgid "Expiration"
+msgstr ""
+
+#: src/paths/instance/reserves/list/AutorizeTipModal.tsx:108
+#, c-format
+msgid "amount of tip"
+msgstr ""
+
+#: src/paths/instance/reserves/list/AutorizeTipModal.tsx:112
+#, c-format
+msgid "Justification"
+msgstr ""
+
+#: src/paths/instance/reserves/list/AutorizeTipModal.tsx:114
+#, c-format
+msgid "reason for the tip"
+msgstr ""
+
+#: src/paths/instance/reserves/list/AutorizeTipModal.tsx:118
+#, c-format
+msgid "URL after tip"
+msgstr ""
+
+#: src/paths/instance/reserves/list/AutorizeTipModal.tsx:119
+#, c-format
+msgid "URL to visit after tip payment"
+msgstr ""
+
+#: src/paths/instance/reserves/list/Table.tsx:65
+#, c-format
+msgid "Reserves not yet funded"
+msgstr ""
+
+#: src/paths/instance/reserves/list/Table.tsx:89
+#, c-format
+msgid "Reserves ready"
+msgstr ""
+
+#: src/paths/instance/reserves/list/Table.tsx:95
+#, c-format
+msgid "add new reserve"
+msgstr ""
+
+#: src/paths/instance/reserves/list/Table.tsx:143
+#, c-format
+msgid "Expires at"
+msgstr ""
+
+#: src/paths/instance/reserves/list/Table.tsx:146
+#, c-format
+msgid "Initial"
+msgstr ""
+
+#: src/paths/instance/reserves/list/Table.tsx:202
+#, c-format
+msgid "delete selected reserve from the database"
+msgstr ""
+
+#: src/paths/instance/reserves/list/Table.tsx:210
+#, c-format
+msgid "authorize new tip from selected reserve"
+msgstr ""
+
+#: src/paths/instance/reserves/list/Table.tsx:237
+#, c-format
+msgid ""
+"There is no ready reserves yet, add more pressing the + sign or fund them"
+msgstr ""
+
+#: src/paths/instance/reserves/list/Table.tsx:264
+#, c-format
+msgid "Expected Balance"
+msgstr ""
+
+#: src/paths/instance/reserves/list/index.tsx:110
+#, c-format
+msgid "could not create the tip"
+msgstr ""
+
+#: src/paths/instance/templates/create/CreatePage.tsx:77
+#, c-format
+msgid "should not be empty"
+msgstr ""
+
+#: src/paths/instance/templates/create/CreatePage.tsx:93
+#, c-format
+msgid "should be greater that 0"
+msgstr ""
+
+#: src/paths/instance/templates/create/CreatePage.tsx:96
+#, c-format
+msgid "can't be empty"
+msgstr ""
+
+#: src/paths/instance/templates/create/CreatePage.tsx:100
+#, c-format
+msgid "to short"
+msgstr ""
+
+#: src/paths/instance/templates/create/CreatePage.tsx:108
+#, c-format
+msgid "just letters and numbers from 2 to 7"
+msgstr ""
+
+#: src/paths/instance/templates/create/CreatePage.tsx:110
+#, c-format
+msgid "size of the key should be 32"
+msgstr ""
+
+#: src/paths/instance/templates/create/CreatePage.tsx:137
+#, c-format
+msgid "Identifier"
+msgstr ""
+
+#: src/paths/instance/templates/create/CreatePage.tsx:138
+#, c-format
+msgid "Name of the template in URLs."
+msgstr ""
+
+#: src/paths/instance/templates/create/CreatePage.tsx:144
+#, c-format
+msgid "Describe what this template stands for"
+msgstr ""
+
+#: src/paths/instance/templates/create/CreatePage.tsx:149
+#, c-format
+msgid "Fixed summary"
+msgstr ""
+
+#: src/paths/instance/templates/create/CreatePage.tsx:150
+#, c-format
+msgid "If specified, this template will create order with the same summary"
+msgstr ""
+
+#: src/paths/instance/templates/create/CreatePage.tsx:154
+#, c-format
+msgid "Fixed price"
+msgstr ""
+
+#: src/paths/instance/templates/create/CreatePage.tsx:155
+#, c-format
+msgid "If specified, this template will create order with the same price"
+msgstr ""
+
+#: src/paths/instance/templates/create/CreatePage.tsx:159
+#, c-format
+msgid "Minimum age"
+msgstr ""
+
+#: src/paths/instance/templates/create/CreatePage.tsx:161
+#, c-format
+msgid "Is this contract restricted to some age?"
+msgstr ""
+
+#: src/paths/instance/templates/create/CreatePage.tsx:165
+#, c-format
+msgid "Payment timeout"
+msgstr ""
+
+#: src/paths/instance/templates/create/CreatePage.tsx:167
+#, c-format
+msgid ""
+"How much time has the customer to complete the payment once the order was "
+"created."
+msgstr ""
+
+#: src/paths/instance/templates/create/CreatePage.tsx:171
+#, c-format
+msgid "Verification algorithm"
+msgstr ""
+
+#: src/paths/instance/templates/create/CreatePage.tsx:172
+#, c-format
+msgid "Algorithm to use to verify transaction in offline mode"
+msgstr ""
+
+#: src/paths/instance/templates/create/CreatePage.tsx:180
+#, c-format
+msgid "Point-of-sale key"
+msgstr ""
+
+#: src/paths/instance/templates/create/CreatePage.tsx:182
+#, c-format
+msgid "Useful to validate the purchase"
+msgstr ""
+
+#: src/paths/instance/templates/create/CreatePage.tsx:196
+#, c-format
+msgid "generate random secret key"
+msgstr ""
+
+#: src/paths/instance/templates/create/CreatePage.tsx:203
+#, c-format
+msgid "random"
+msgstr ""
+
+#: src/paths/instance/templates/create/CreatePage.tsx:208
+#, c-format
+msgid "show secret key"
+msgstr ""
+
+#: src/paths/instance/templates/create/CreatePage.tsx:209
+#, c-format
+msgid "hide secret key"
+msgstr ""
+
+#: src/paths/instance/templates/create/CreatePage.tsx:216
+#, c-format
+msgid "hide"
+msgstr ""
+
+#: src/paths/instance/templates/create/CreatePage.tsx:218
+#, c-format
+msgid "show"
+msgstr ""
+
+#: src/paths/instance/templates/create/index.tsx:52
+#, c-format
+msgid "could not inform template"
+msgstr ""
+
+#: src/paths/instance/templates/use/UsePage.tsx:54
+#, c-format
+msgid "Amount is required"
+msgstr ""
+
+#: src/paths/instance/templates/use/UsePage.tsx:58
+#, c-format
+msgid "Order summary is required"
+msgstr ""
+
+#: src/paths/instance/templates/use/UsePage.tsx:86
+#, c-format
+msgid "New order for template"
+msgstr ""
+
+#: src/paths/instance/templates/use/UsePage.tsx:108
+#, c-format
+msgid "Amount of the order"
+msgstr ""
+
+#: src/paths/instance/templates/use/UsePage.tsx:113
+#, c-format
+msgid "Order summary"
+msgstr ""
+
+#: src/paths/instance/templates/use/index.tsx:92
+#, c-format
+msgid "could not create order from template"
+msgstr ""
+
+#: src/paths/instance/templates/qr/QrPage.tsx:131
+#, c-format
+msgid ""
+"Here you can specify a default value for fields that are not fixed. Default "
+"values can be edited by the customer before the payment."
+msgstr ""
+
+#: src/paths/instance/templates/qr/QrPage.tsx:148
+#, c-format
+msgid "Fixed amount"
+msgstr ""
+
+#: src/paths/instance/templates/qr/QrPage.tsx:149
+#, c-format
+msgid "Default amount"
+msgstr ""
+
+#: src/paths/instance/templates/qr/QrPage.tsx:161
+#, c-format
+msgid "Default summary"
+msgstr ""
+
+#: src/paths/instance/templates/qr/QrPage.tsx:177
+#, c-format
+msgid "Print"
+msgstr ""
+
+#: src/paths/instance/templates/qr/QrPage.tsx:184
+#, c-format
+msgid "Setup TOTP"
+msgstr ""
+
+#: src/paths/instance/templates/list/Table.tsx:65
+#, c-format
+msgid "Templates"
+msgstr ""
+
+#: src/paths/instance/templates/list/Table.tsx:70
+#, c-format
+msgid "add new templates"
+msgstr ""
+
+#: src/paths/instance/templates/list/Table.tsx:142
+#, c-format
+msgid "load more templates before the first one"
+msgstr ""
+
+#: src/paths/instance/templates/list/Table.tsx:146
+#, c-format
+msgid "load newer templates"
+msgstr ""
+
+#: src/paths/instance/templates/list/Table.tsx:181
+#, c-format
+msgid "delete selected templates from the database"
+msgstr ""
+
+#: src/paths/instance/templates/list/Table.tsx:188
+#, c-format
+msgid "use template to create new order"
+msgstr ""
+
+#: src/paths/instance/templates/list/Table.tsx:195
+#, c-format
+msgid "create qr code for the template"
+msgstr ""
+
+#: src/paths/instance/templates/list/Table.tsx:210
+#, c-format
+msgid "load more templates after the last one"
+msgstr ""
+
+#: src/paths/instance/templates/list/Table.tsx:214
+#, c-format
+msgid "load older templates"
+msgstr ""
+
+#: src/paths/instance/templates/list/Table.tsx:231
+#, c-format
+msgid "There is no templates yet, add more pressing the + sign"
+msgstr ""
+
+#: src/paths/instance/templates/list/index.tsx:104
+#, c-format
+msgid "template delete successfully"
+msgstr ""
+
+#: src/paths/instance/templates/list/index.tsx:110
+#, c-format
+msgid "could not delete the template"
+msgstr ""
+
+#: src/paths/instance/templates/update/index.tsx:90
+#, c-format
+msgid "could not update template"
+msgstr ""
+
+#: src/paths/instance/webhooks/create/CreatePage.tsx:57
+#, c-format
+msgid "should be one of '%1$s'"
+msgstr ""
+
+#: src/paths/instance/webhooks/create/CreatePage.tsx:85
+#, c-format
+msgid "Webhook ID to use"
+msgstr ""
+
+#: src/paths/instance/webhooks/create/CreatePage.tsx:89
+#, c-format
+msgid "Event"
+msgstr ""
+
+#: src/paths/instance/webhooks/create/CreatePage.tsx:90
+#, c-format
+msgid "The event of the webhook: why the webhook is used"
+msgstr ""
+
+#: src/paths/instance/webhooks/create/CreatePage.tsx:94
+#, c-format
+msgid "Method"
+msgstr ""
+
+#: src/paths/instance/webhooks/create/CreatePage.tsx:95
+#, c-format
+msgid "Method used by the webhook"
+msgstr ""
+
+#: src/paths/instance/webhooks/create/CreatePage.tsx:99
+#, c-format
+msgid "URL"
+msgstr ""
+
+#: src/paths/instance/webhooks/create/CreatePage.tsx:100
+#, c-format
+msgid "URL of the webhook where the customer will be redirected"
+msgstr ""
+
+#: src/paths/instance/webhooks/create/CreatePage.tsx:104
+#, c-format
+msgid "Header"
+msgstr ""
+
+#: src/paths/instance/webhooks/create/CreatePage.tsx:106
+#, c-format
+msgid "Header template of the webhook"
+msgstr ""
+
+#: src/paths/instance/webhooks/create/CreatePage.tsx:111
+#, c-format
+msgid "Body"
+msgstr ""
+
+#: src/paths/instance/webhooks/create/CreatePage.tsx:112
+#, c-format
+msgid "Body template by the webhook"
+msgstr ""
+
+#: src/paths/instance/webhooks/list/Table.tsx:61
+#, c-format
+msgid "Webhooks"
+msgstr ""
+
+#: src/paths/instance/webhooks/list/Table.tsx:66
+#, c-format
+msgid "add new webhooks"
+msgstr ""
+
+#: src/paths/instance/webhooks/list/Table.tsx:137
+#, c-format
+msgid "load more webhooks before the first one"
+msgstr ""
+
+#: src/paths/instance/webhooks/list/Table.tsx:141
+#, c-format
+msgid "load newer webhooks"
+msgstr ""
+
+#: src/paths/instance/webhooks/list/Table.tsx:151
+#, c-format
+msgid "Event type"
+msgstr ""
+
+#: src/paths/instance/webhooks/list/Table.tsx:176
+#, c-format
+msgid "delete selected webhook from the database"
+msgstr ""
+
+#: src/paths/instance/webhooks/list/Table.tsx:198
+#, c-format
+msgid "load more webhooks after the last one"
+msgstr ""
+
+#: src/paths/instance/webhooks/list/Table.tsx:202
+#, c-format
+msgid "load older webhooks"
+msgstr ""
+
+#: src/paths/instance/webhooks/list/Table.tsx:219
+#, c-format
+msgid "There is no webhooks yet, add more pressing the + sign"
+msgstr ""
+
+#: src/paths/instance/webhooks/list/index.tsx:94
+#, c-format
+msgid "webhook delete successfully"
+msgstr ""
+
+#: src/paths/instance/webhooks/list/index.tsx:100
+#, c-format
+msgid "could not delete the webhook"
+msgstr ""
+
+#: src/paths/instance/transfers/create/CreatePage.tsx:63
+#, c-format
+msgid "check the id, does not look valid"
+msgstr ""
+
+#: src/paths/instance/transfers/create/CreatePage.tsx:65
+#, c-format
+msgid "should have 52 characters, current %1$s"
+msgstr ""
+
+#: src/paths/instance/transfers/create/CreatePage.tsx:72
+#, c-format
+msgid "URL doesn't have the right format"
+msgstr ""
+
+#: src/paths/instance/transfers/create/CreatePage.tsx:98
+#, c-format
+msgid "Credited bank account"
+msgstr ""
+
+#: src/paths/instance/transfers/create/CreatePage.tsx:100
+#, c-format
+msgid "Select one account"
+msgstr ""
+
+#: src/paths/instance/transfers/create/CreatePage.tsx:101
+#, c-format
+msgid "Bank account of the merchant where the payment was received"
+msgstr ""
+
+#: src/paths/instance/transfers/create/CreatePage.tsx:105
+#, c-format
+msgid "Wire transfer ID"
+msgstr ""
+
+#: src/paths/instance/transfers/create/CreatePage.tsx:107
+#, c-format
+msgid ""
+"unique identifier of the wire transfer used by the exchange, must be 52 "
+"characters long"
+msgstr ""
+
+#: src/paths/instance/transfers/create/CreatePage.tsx:112
+#, c-format
+msgid ""
+"Base URL of the exchange that made the transfer, should have been in the "
+"wire transfer subject"
+msgstr ""
+
+#: src/paths/instance/transfers/create/CreatePage.tsx:117
+#, c-format
+msgid "Amount credited"
+msgstr ""
+
+#: src/paths/instance/transfers/create/CreatePage.tsx:118
+#, c-format
+msgid "Actual amount that was wired to the merchant's bank account"
+msgstr ""
+
+#: src/paths/instance/transfers/create/index.tsx:58
+#, c-format
+msgid "could not inform transfer"
+msgstr ""
+
+#: src/paths/instance/transfers/list/Table.tsx:61
+#, c-format
+msgid "Transfers"
+msgstr ""
+
+#: src/paths/instance/transfers/list/Table.tsx:66
+#, c-format
+msgid "add new transfer"
+msgstr ""
+
+#: src/paths/instance/transfers/list/Table.tsx:129
+#, c-format
+msgid "load more transfers before the first one"
+msgstr ""
+
+#: src/paths/instance/transfers/list/Table.tsx:133
+#, c-format
+msgid "load newer transfers"
+msgstr ""
+
+#: src/paths/instance/transfers/list/Table.tsx:143
+#, c-format
+msgid "Credit"
+msgstr ""
+
+#: src/paths/instance/transfers/list/Table.tsx:152
+#, c-format
+msgid "Confirmed"
+msgstr ""
+
+#: src/paths/instance/transfers/list/Table.tsx:155
+#, c-format
+msgid "Verified"
+msgstr ""
+
+#: src/paths/instance/transfers/list/Table.tsx:158
+#, c-format
+msgid "Executed at"
+msgstr ""
+
+#: src/paths/instance/transfers/list/Table.tsx:171
+#, c-format
+msgid "yes"
+msgstr ""
+
+#: src/paths/instance/transfers/list/Table.tsx:171
+#, c-format
+msgid "no"
+msgstr ""
+
+#: src/paths/instance/transfers/list/Table.tsx:181
+#, c-format
+msgid "unknown"
+msgstr ""
+
+#: src/paths/instance/transfers/list/Table.tsx:187
+#, c-format
+msgid "delete selected transfer from the database"
+msgstr ""
+
+#: src/paths/instance/transfers/list/Table.tsx:202
+#, c-format
+msgid "load more transfer after the last one"
+msgstr ""
+
+#: src/paths/instance/transfers/list/Table.tsx:206
+#, c-format
+msgid "load older transfers"
+msgstr ""
+
+#: src/paths/instance/transfers/list/Table.tsx:223
+#, c-format
+msgid "There is no transfer yet, add more pressing the + sign"
+msgstr ""
+
+#: src/paths/instance/transfers/list/ListPage.tsx:79
+#, c-format
+msgid "filter by account address"
+msgstr ""
+
+#: src/paths/instance/transfers/list/ListPage.tsx:100
+#, c-format
+msgid "only show wire transfers confirmed by the merchant"
+msgstr ""
+
+#: src/paths/instance/transfers/list/ListPage.tsx:110
+#, c-format
+msgid "only show wire transfers claimed by the exchange"
+msgstr ""
+
+#: src/paths/instance/transfers/list/ListPage.tsx:113
+#, c-format
+msgid "Unverified"
+msgstr ""
+
+#: src/paths/admin/create/CreatePage.tsx:69
+#, c-format
+msgid "is not valid"
+msgstr ""
+
+#: src/paths/admin/create/CreatePage.tsx:94
+#, c-format
+msgid "is not a number"
+msgstr ""
+
+#: src/paths/admin/create/CreatePage.tsx:96
+#, c-format
+msgid "must be 1 or greater"
+msgstr ""
+
+#: src/paths/admin/create/CreatePage.tsx:107
+#, c-format
+msgid "max 7 lines"
+msgstr ""
+
+#: src/paths/admin/create/CreatePage.tsx:178
+#, c-format
+msgid "change authorization configuration"
+msgstr ""
+
+#: src/paths/admin/create/CreatePage.tsx:217
+#, c-format
+msgid "Need to complete marked fields and choose authorization method"
+msgstr ""
+
+#: src/components/form/InputPaytoForm.tsx:82
+#, c-format
+msgid "This is not a valid bitcoin address."
+msgstr ""
+
+#: src/components/form/InputPaytoForm.tsx:95
+#, c-format
+msgid "This is not a valid Ethereum address."
+msgstr ""
+
+#: src/components/form/InputPaytoForm.tsx:118
+#, c-format
+msgid "IBAN numbers usually have more that 4 digits"
+msgstr ""
+
+#: src/components/form/InputPaytoForm.tsx:120
+#, c-format
+msgid "IBAN numbers usually have less that 34 digits"
+msgstr ""
+
+#: src/components/form/InputPaytoForm.tsx:128
+#, c-format
+msgid "IBAN country code not found"
+msgstr ""
+
+#: src/components/form/InputPaytoForm.tsx:153
+#, c-format
+msgid "IBAN number is not valid, checksum is wrong"
+msgstr ""
+
+#: src/components/form/InputPaytoForm.tsx:248
+#, c-format
+msgid "Target type"
+msgstr ""
+
+#: src/components/form/InputPaytoForm.tsx:249
+#, c-format
+msgid "Method to use for wire transfer"
+msgstr ""
+
+#: src/components/form/InputPaytoForm.tsx:258
+#, c-format
+msgid "Routing"
+msgstr ""
+
+#: src/components/form/InputPaytoForm.tsx:259
+#, c-format
+msgid "Routing number."
+msgstr ""
+
+#: src/components/form/InputPaytoForm.tsx:263
+#, c-format
+msgid "Account"
+msgstr ""
+
+#: src/components/form/InputPaytoForm.tsx:264
+#, c-format
+msgid "Account number."
+msgstr ""
+
+#: src/components/form/InputPaytoForm.tsx:273
+#, c-format
+msgid "Business Identifier Code."
+msgstr ""
+
+#: src/components/form/InputPaytoForm.tsx:282
+#, c-format
+msgid "Bank Account Number."
+msgstr ""
+
+#: src/components/form/InputPaytoForm.tsx:292
+#, c-format
+msgid "Unified Payment Interface."
+msgstr ""
+
+#: src/components/form/InputPaytoForm.tsx:301
+#, c-format
+msgid "Bitcoin protocol."
+msgstr ""
+
+#: src/components/form/InputPaytoForm.tsx:310
+#, c-format
+msgid "Ethereum protocol."
+msgstr ""
+
+#: src/components/form/InputPaytoForm.tsx:319
+#, c-format
+msgid "Interledger protocol."
+msgstr ""
+
+#: src/components/form/InputPaytoForm.tsx:328
+#, c-format
+msgid "Host"
+msgstr ""
+
+#: src/components/form/InputPaytoForm.tsx:329
+#, c-format
+msgid "Bank host."
+msgstr ""
+
+#: src/components/form/InputPaytoForm.tsx:334
+#, c-format
+msgid "Bank account."
+msgstr ""
+
+#: src/components/form/InputPaytoForm.tsx:343
+#, c-format
+msgid "Bank account owner's name."
+msgstr ""
+
+#: src/components/form/InputPaytoForm.tsx:370
+#, c-format
+msgid "No accounts yet."
+msgstr ""
+
+#: src/components/instance/DefaultInstanceFormFields.tsx:52
+#, c-format
+msgid ""
+"Name of the instance in URLs. The 'default' instance is special in that it "
+"is used to administer other instances."
+msgstr ""
+
+#: src/components/instance/DefaultInstanceFormFields.tsx:58
+#, c-format
+msgid "Business name"
+msgstr ""
+
+#: src/components/instance/DefaultInstanceFormFields.tsx:59
+#, c-format
+msgid "Legal name of the business represented by this instance."
+msgstr ""
+
+#: src/components/instance/DefaultInstanceFormFields.tsx:64
+#, c-format
+msgid "Email"
+msgstr ""
+
+#: src/components/instance/DefaultInstanceFormFields.tsx:65
+#, c-format
+msgid "Contact email"
+msgstr ""
+
+#: src/components/instance/DefaultInstanceFormFields.tsx:70
+#, c-format
+msgid "Website URL"
+msgstr ""
+
+#: src/components/instance/DefaultInstanceFormFields.tsx:71
+#, c-format
+msgid "URL."
+msgstr ""
+
+#: src/components/instance/DefaultInstanceFormFields.tsx:76
+#, c-format
+msgid "Logo"
+msgstr ""
+
+#: src/components/instance/DefaultInstanceFormFields.tsx:77
+#, c-format
+msgid "Logo image."
+msgstr ""
+
+#: src/components/instance/DefaultInstanceFormFields.tsx:82
+#, c-format
+msgid "Bank account"
+msgstr ""
+
+#: src/components/instance/DefaultInstanceFormFields.tsx:83
+#, c-format
+msgid "URI specifying bank account for crediting revenue."
+msgstr ""
+
+#: src/components/instance/DefaultInstanceFormFields.tsx:88
+#, c-format
+msgid "Default max deposit fee"
+msgstr ""
+
+#: src/components/instance/DefaultInstanceFormFields.tsx:89
+#, c-format
+msgid ""
+"Maximum deposit fees this merchant is willing to pay per order by default."
+msgstr ""
+
+#: src/components/instance/DefaultInstanceFormFields.tsx:94
+#, c-format
+msgid "Default max wire fee"
+msgstr ""
+
+#: src/components/instance/DefaultInstanceFormFields.tsx:95
+#, c-format
+msgid ""
+"Maximum wire fees this merchant is willing to pay per wire transfer by "
+"default."
+msgstr ""
+
+#: src/components/instance/DefaultInstanceFormFields.tsx:100
+#, c-format
+msgid "Default wire fee amortization"
+msgstr ""
+
+#: src/components/instance/DefaultInstanceFormFields.tsx:101
+#, c-format
+msgid ""
+"Number of orders excess wire transfer fees will be divided by to compute per "
+"order surcharge."
+msgstr ""
+
+#: src/components/instance/DefaultInstanceFormFields.tsx:107
+#, c-format
+msgid "Physical location of the merchant."
+msgstr ""
+
+#: src/components/instance/DefaultInstanceFormFields.tsx:114
+#, c-format
+msgid "Jurisdiction"
+msgstr ""
+
+#: src/components/instance/DefaultInstanceFormFields.tsx:115
+#, c-format
+msgid "Jurisdiction for legal disputes with the merchant."
+msgstr ""
+
+#: src/components/instance/DefaultInstanceFormFields.tsx:122
+#, c-format
+msgid "Default payment delay"
+msgstr ""
+
+#: src/components/instance/DefaultInstanceFormFields.tsx:124
+#, c-format
+msgid ""
+"Time customers have to pay an order before the offer expires by default."
+msgstr ""
+
+#: src/components/instance/DefaultInstanceFormFields.tsx:129
+#, c-format
+msgid "Default wire transfer delay"
+msgstr ""
+
+#: src/components/instance/DefaultInstanceFormFields.tsx:130
+#, c-format
+msgid ""
+"Maximum time an exchange is allowed to delay wiring funds to the merchant, "
+"enabling it to aggregate smaller payments into larger wire transfers and "
+"reducing wire fees."
+msgstr ""
+
+#: src/paths/instance/update/UpdatePage.tsx:164
+#, c-format
+msgid "Instance id"
+msgstr ""
+
+#: src/paths/instance/update/UpdatePage.tsx:173
+#, c-format
+msgid "Change the authorization method use for this instance."
+msgstr ""
+
+#: src/paths/instance/update/UpdatePage.tsx:182
+#, c-format
+msgid "Manage access token"
+msgstr ""
+
+#: src/paths/instance/update/index.tsx:112
+#, c-format
+msgid "Failed to create instance"
+msgstr ""
+
+#: src/components/exception/login.tsx:74
+#, c-format
+msgid "Login required"
+msgstr ""
+
+#: src/components/exception/login.tsx:80
+#, c-format
+msgid "Please enter your access token."
+msgstr ""
+
+#: src/components/exception/login.tsx:108
+#, c-format
+msgid "Access Token"
+msgstr ""
+
+#: src/InstanceRoutes.tsx:171
+#, c-format
+msgid "The request to the backend take too long and was cancelled"
+msgstr ""
+
+#: src/InstanceRoutes.tsx:172
+#, c-format
+msgid "Diagnostic from %1$s is \"%2$s\""
+msgstr ""
+
+#: src/InstanceRoutes.tsx:178
+#, c-format
+msgid "The backend reported a problem: HTTP status #%1$s"
+msgstr ""
+
+#: src/InstanceRoutes.tsx:179
+#, c-format
+msgid "Diagnostic from %1$s is '%2$s'"
+msgstr ""
+
+#: src/InstanceRoutes.tsx:196
+#, c-format
+msgid "Access denied"
+msgstr ""
+
+#: src/InstanceRoutes.tsx:197
+#, c-format
+msgid "The access token provided is invalid."
+msgstr ""
+
+#: src/InstanceRoutes.tsx:212
+#, c-format
+msgid "No 'default' instance configured yet."
+msgstr ""
+
+#: src/InstanceRoutes.tsx:213
+#, c-format
+msgid "Create a 'default' instance to begin using the merchant backoffice."
+msgstr ""
+
+#: src/InstanceRoutes.tsx:630
+#, c-format
+msgid "The access token provided is invalid"
+msgstr ""
+
+#: src/InstanceRoutes.tsx:664
+#, c-format
+msgid "Hide for today"
+msgstr ""
+
+#: src/components/menu/SideBar.tsx:82
+#, c-format
+msgid "Instance"
+msgstr ""
+
+#: src/components/menu/SideBar.tsx:91
+#, c-format
+msgid "Settings"
+msgstr "Impostazioni"
+
+#: src/components/menu/SideBar.tsx:167
+#, c-format
+msgid "Connection"
+msgstr ""
+
+#: src/components/menu/SideBar.tsx:209
+#, c-format
+msgid "New"
+msgstr ""
+
+#: src/components/menu/SideBar.tsx:219
+#, c-format
+msgid "List"
+msgstr ""
+
+#: src/components/menu/SideBar.tsx:234
+#, c-format
+msgid "Log out"
+msgstr ""
+
+#: src/ApplicationReadyRoutes.tsx:71
+#, c-format
+msgid "Check your token is valid"
+msgstr ""
+
+#: src/ApplicationReadyRoutes.tsx:90
+#, c-format
+msgid "Couldn't access the server."
+msgstr ""
+
+#: src/ApplicationReadyRoutes.tsx:91
+#, c-format
+msgid "Could not infer instance id from url %1$s"
+msgstr ""
+
+#: src/Application.tsx:104
+#, c-format
+msgid "Server not found"
+msgstr ""
+
+#: src/Application.tsx:118
+#, c-format
+msgid "Server response with an error code"
+msgstr ""
+
+#: src/Application.tsx:120
+#, c-format
+msgid "Got message %1$s from %2$s"
+msgstr ""
+
+#: src/Application.tsx:131
+#, c-format
+msgid "Response from server is unreadable, http status: %1$s"
+msgstr ""
+
+#: src/Application.tsx:144
+#, c-format
+msgid "Unexpected Error"
+msgstr ""
+
+#: src/components/form/InputArray.tsx:101
+#, c-format
+msgid "The value %1$s is invalid for a payment url"
+msgstr ""
+
+#: src/components/form/InputArray.tsx:110
+#, c-format
+msgid "add element to the list"
+msgstr ""
+
+#: src/components/form/InputArray.tsx:112
+#, c-format
+msgid "add"
+msgstr ""
+
+#: src/components/form/InputSecured.tsx:37
+#, c-format
+msgid "Deleting"
+msgstr ""
+
+#: src/components/form/InputSecured.tsx:41
+#, c-format
+msgid "Changing"
+msgstr ""
+
+#: src/paths/instance/orders/create/OrderCreatedSuccessfully.tsx:87
+#, c-format
+msgid "Order ID"
+msgstr ""
+
+#: src/paths/instance/orders/create/OrderCreatedSuccessfully.tsx:101
+#, c-format
+msgid "Payment URL"
+msgstr ""
diff --git a/packages/auditor-backoffice-ui/src/i18n/poheader 
b/packages/auditor-backoffice-ui/src/i18n/poheader
new file mode 100644
index 000000000..7ddcf49b8
--- /dev/null
+++ b/packages/auditor-backoffice-ui/src/i18n/poheader
@@ -0,0 +1,27 @@
+#  This file is part of GNU Taler
+#  (C) 2021-2023 Taler Systems S.A.
+
+#  GNU Taler is free software; you can redistribute it and/or modify it under 
the
+#  terms of the GNU General Public License as published by the Free Software
+#  Foundation; either version 3, or (at your option) any later version.
+
+#  GNU Taler is distributed in the hope that it will be useful, but WITHOUT ANY
+#  WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS 
FOR
+#  A PARTICULAR PURPOSE.  See the GNU General Public License for more details.
+
+#  You should have received a copy of the GNU General Public License along with
+#  GNU Taler; see the file COPYING.  If not, see <http://www.gnu.org/licenses/>
+
+#
+#, fuzzy
+msgid ""
+msgstr ""
+"Project-Id-Version: Taler Wallet\n"
+"Report-Msgid-Bugs-To: taler@gnu.org\n"
+"PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n"
+"Last-Translator: FULL NAME <EMAIL@ADDRESS>\n"
+"Language-Team: LANGUAGE <LL@li.org>\n"
+"MIME-Version: 1.0\n"
+"Content-Type: text/plain; charset=UTF-8\n"
+"Content-Transfer-Encoding: 8bit\n"
+"Plural-Forms: nplurals=2; plural=(n != 1);\n"
diff --git a/packages/auditor-backoffice-ui/src/i18n/strings-prelude 
b/packages/auditor-backoffice-ui/src/i18n/strings-prelude
new file mode 100644
index 000000000..6c68662de
--- /dev/null
+++ b/packages/auditor-backoffice-ui/src/i18n/strings-prelude
@@ -0,0 +1,19 @@
+/*
+ This file is part of GNU Taler
+ (C) 2021-2023 Taler Systems S.A.
+
+ GNU Taler is free software; you can redistribute it and/or modify it under the
+ terms of the GNU General Public License as published by the Free Software
+ Foundation; either version 3, or (at your option) any later version.
+
+ GNU Taler is distributed in the hope that it will be useful, but WITHOUT ANY
+ WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
+ A PARTICULAR PURPOSE.  See the GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License along with
+ GNU Taler; see the file COPYING.  If not, see <http://www.gnu.org/licenses/>
+ */
+
+/*eslint quote-props: ["error", "consistent"]*/
+export const strings: {[s: string]: any} = {};
+
diff --git a/packages/auditor-backoffice-ui/src/i18n/strings.ts 
b/packages/auditor-backoffice-ui/src/i18n/strings.ts
new file mode 100644
index 000000000..65dc41358
--- /dev/null
+++ b/packages/auditor-backoffice-ui/src/i18n/strings.ts
@@ -0,0 +1,9655 @@
+/*
+ This file is part of GNU Taler
+ (C) 2021-2023 Taler Systems S.A.
+
+ GNU Taler is free software; you can redistribute it and/or modify it under the
+ terms of the GNU General Public License as published by the Free Software
+ Foundation; either version 3, or (at your option) any later version.
+
+ GNU Taler is distributed in the hope that it will be useful, but WITHOUT ANY
+ WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
+ A PARTICULAR PURPOSE.  See the GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License along with
+ GNU Taler; see the file COPYING.  If not, see <http://www.gnu.org/licenses/>
+ */
+
+/*eslint quote-props: ["error", "consistent"]*/
+export const strings: {[s: string]: any} = {};
+
+strings['de'] = {
+  "domain": "messages",
+  "locale_data": {
+    "messages": {
+      "": {
+        "domain": "messages",
+        "plural_forms": "nplurals=2; plural=(n != 1);",
+        "lang": ""
+      },
+      "Cancel": [
+        ""
+      ],
+      "%1$s": [
+        ""
+      ],
+      "Close": [
+        ""
+      ],
+      "Continue": [
+        ""
+      ],
+      "Clear": [
+        ""
+      ],
+      "Confirm": [
+        ""
+      ],
+      "is not the same as the current access token": [
+        ""
+      ],
+      "cannot be empty": [
+        ""
+      ],
+      "cannot be the same as the old token": [
+        ""
+      ],
+      "is not the same": [
+        ""
+      ],
+      "You are updating the access token from instance with id %1$s": [
+        ""
+      ],
+      "Old access token": [
+        ""
+      ],
+      "access token currently in use": [
+        ""
+      ],
+      "New access token": [
+        ""
+      ],
+      "next access token to be used": [
+        ""
+      ],
+      "Repeat access token": [
+        ""
+      ],
+      "confirm the same access token": [
+        ""
+      ],
+      "Clearing the access token will mean public access to the instance": [
+        ""
+      ],
+      "cannot be the same as the old access token": [
+        ""
+      ],
+      "You are setting the access token for the new instance": [
+        ""
+      ],
+      "With external authorization method no check will be done by the 
merchant backend": [
+        ""
+      ],
+      "Set external authorization": [
+        ""
+      ],
+      "Set access token": [
+        ""
+      ],
+      "Operation in progress...": [
+        ""
+      ],
+      "The operation will be automatically canceled after %1$s seconds": [
+        ""
+      ],
+      "Instances": [
+        ""
+      ],
+      "Delete": [
+        ""
+      ],
+      "add new instance": [
+        ""
+      ],
+      "ID": [
+        ""
+      ],
+      "Name": [
+        ""
+      ],
+      "Edit": [
+        ""
+      ],
+      "Purge": [
+        ""
+      ],
+      "There is no instances yet, add more pressing the + sign": [
+        ""
+      ],
+      "Only show active instances": [
+        ""
+      ],
+      "Active": [
+        ""
+      ],
+      "Only show deleted instances": [
+        ""
+      ],
+      "Deleted": [
+        ""
+      ],
+      "Show all instances": [
+        ""
+      ],
+      "All": [
+        ""
+      ],
+      "Instance \"%1$s\" (ID: %2$s) has been deleted": [
+        ""
+      ],
+      "Failed to delete instance": [
+        ""
+      ],
+      "Instance '%1$s' (ID: %2$s) has been disabled": [
+        ""
+      ],
+      "Failed to purge instance": [
+        ""
+      ],
+      "Pending KYC verification": [
+        ""
+      ],
+      "Timed out": [
+        ""
+      ],
+      "Exchange": [
+        ""
+      ],
+      "Target account": [
+        ""
+      ],
+      "KYC URL": [
+        ""
+      ],
+      "Code": [
+        ""
+      ],
+      "Http Status": [
+        ""
+      ],
+      "No pending kyc verification!": [
+        ""
+      ],
+      "change value to unknown date": [
+        ""
+      ],
+      "change value to empty": [
+        ""
+      ],
+      "clear": [
+        ""
+      ],
+      "change value to never": [
+        ""
+      ],
+      "never": [
+        ""
+      ],
+      "Country": [
+        ""
+      ],
+      "Address": [
+        ""
+      ],
+      "Building number": [
+        ""
+      ],
+      "Building name": [
+        ""
+      ],
+      "Street": [
+        ""
+      ],
+      "Post code": [
+        ""
+      ],
+      "Town location": [
+        ""
+      ],
+      "Town": [
+        ""
+      ],
+      "District": [
+        ""
+      ],
+      "Country subdivision": [
+        ""
+      ],
+      "Product id": [
+        ""
+      ],
+      "Description": [
+        ""
+      ],
+      "Product": [
+        ""
+      ],
+      "search products by it's description or id": [
+        ""
+      ],
+      "no products found with that description": [
+        ""
+      ],
+      "You must enter a valid product identifier.": [
+        ""
+      ],
+      "Quantity must be greater than 0!": [
+        ""
+      ],
+      "This quantity exceeds remaining stock. Currently, only %1$s units 
remain unreserved in stock.": [
+        ""
+      ],
+      "Quantity": [
+        ""
+      ],
+      "how many products will be added": [
+        ""
+      ],
+      "Add from inventory": [
+        ""
+      ],
+      "Image should be smaller than 1 MB": [
+        ""
+      ],
+      "Add": [
+        ""
+      ],
+      "Remove": [
+        ""
+      ],
+      "No taxes configured for this product.": [
+        ""
+      ],
+      "Amount": [
+        ""
+      ],
+      "Taxes can be in currencies that differ from the main currency used by 
the merchant.": [
+        ""
+      ],
+      "Enter currency and value separated with a colon, e.g. 
&quot;USD:2.3&quot;.": [
+        ""
+      ],
+      "Legal name of the tax, e.g. VAT or import duties.": [
+        ""
+      ],
+      "add tax to the tax list": [
+        ""
+      ],
+      "describe and add a product that is not in the inventory list": [
+        ""
+      ],
+      "Add custom product": [
+        ""
+      ],
+      "Complete information of the product": [
+        ""
+      ],
+      "Image": [
+        ""
+      ],
+      "photo of the product": [
+        ""
+      ],
+      "full product description": [
+        ""
+      ],
+      "Unit": [
+        ""
+      ],
+      "name of the product unit": [
+        ""
+      ],
+      "Price": [
+        ""
+      ],
+      "amount in the current currency": [
+        ""
+      ],
+      "Taxes": [
+        ""
+      ],
+      "image": [
+        ""
+      ],
+      "description": [
+        ""
+      ],
+      "quantity": [
+        ""
+      ],
+      "unit price": [
+        ""
+      ],
+      "total price": [
+        ""
+      ],
+      "required": [
+        ""
+      ],
+      "not valid": [
+        ""
+      ],
+      "must be greater than 0": [
+        ""
+      ],
+      "not a valid json": [
+        ""
+      ],
+      "should be in the future": [
+        ""
+      ],
+      "refund deadline cannot be before pay deadline": [
+        ""
+      ],
+      "wire transfer deadline cannot be before refund deadline": [
+        ""
+      ],
+      "wire transfer deadline cannot be before pay deadline": [
+        ""
+      ],
+      "should have a refund deadline": [
+        ""
+      ],
+      "auto refund cannot be after refund deadline": [
+        ""
+      ],
+      "Manage products in order": [
+        ""
+      ],
+      "Manage list of products in the order.": [
+        ""
+      ],
+      "Remove this product from the order.": [
+        ""
+      ],
+      "Total price": [
+        ""
+      ],
+      "total product price added up": [
+        ""
+      ],
+      "Amount to be paid by the customer": [
+        ""
+      ],
+      "Order price": [
+        ""
+      ],
+      "final order price": [
+        ""
+      ],
+      "Summary": [
+        ""
+      ],
+      "Title of the order to be shown to the customer": [
+        ""
+      ],
+      "Shipping and Fulfillment": [
+        ""
+      ],
+      "Delivery date": [
+        ""
+      ],
+      "Deadline for physical delivery assured by the merchant.": [
+        ""
+      ],
+      "Location": [
+        ""
+      ],
+      "address where the products will be delivered": [
+        ""
+      ],
+      "Fulfillment URL": [
+        ""
+      ],
+      "URL to which the user will be redirected after successful payment.": [
+        ""
+      ],
+      "Taler payment options": [
+        ""
+      ],
+      "Override default Taler payment settings for this order": [
+        ""
+      ],
+      "Payment deadline": [
+        ""
+      ],
+      "Deadline for the customer to pay for the offer before it expires. 
Inventory products will be reserved until this deadline.": [
+        ""
+      ],
+      "Refund deadline": [
+        ""
+      ],
+      "Time until which the order can be refunded by the merchant.": [
+        ""
+      ],
+      "Wire transfer deadline": [
+        ""
+      ],
+      "Deadline for the exchange to make the wire transfer.": [
+        ""
+      ],
+      "Auto-refund deadline": [
+        ""
+      ],
+      "Time until which the wallet will automatically check for refunds 
without user interaction.": [
+        ""
+      ],
+      "Maximum deposit fee": [
+        ""
+      ],
+      "Maximum deposit fees the merchant is willing to cover for this order. 
Higher deposit fees must be covered in full by the consumer.": [
+        ""
+      ],
+      "Maximum wire fee": [
+        ""
+      ],
+      "Maximum aggregate wire fees the merchant is willing to cover for this 
order. Wire fees exceeding this amount are to be covered by the customers.": [
+        ""
+      ],
+      "Wire fee amortization": [
+        ""
+      ],
+      "Factor by which wire fees exceeding the above threshold are divided to 
determine the share of excess wire fees to be paid explicitly by the 
consumer.": [
+        ""
+      ],
+      "Create token": [
+        ""
+      ],
+      "Uncheck this option if the merchant backend generated an order ID with 
enough entropy to prevent adversarial claims.": [
+        ""
+      ],
+      "Minimum age required": [
+        ""
+      ],
+      "Any value greater than 0 will limit the coins able be used to pay this 
contract. If empty the age restriction will be defined by the products": [
+        ""
+      ],
+      "Min age defined by the producs is %1$s": [
+        ""
+      ],
+      "Additional information": [
+        ""
+      ],
+      "Custom information to be included in the contract for this order.": [
+        ""
+      ],
+      "You must enter a value in JavaScript Object Notation (JSON).": [
+        ""
+      ],
+      "days": [
+        ""
+      ],
+      "hours": [
+        ""
+      ],
+      "minutes": [
+        ""
+      ],
+      "seconds": [
+        ""
+      ],
+      "forever": [
+        ""
+      ],
+      "%1$sM": [
+        ""
+      ],
+      "%1$sY": [
+        ""
+      ],
+      "%1$sd": [
+        ""
+      ],
+      "%1$sh": [
+        ""
+      ],
+      "%1$smin": [
+        ""
+      ],
+      "%1$ssec": [
+        ""
+      ],
+      "Orders": [
+        ""
+      ],
+      "create order": [
+        ""
+      ],
+      "load newer orders": [
+        ""
+      ],
+      "Date": [
+        ""
+      ],
+      "Refund": [
+        ""
+      ],
+      "copy url": [
+        ""
+      ],
+      "load older orders": [
+        ""
+      ],
+      "No orders have been found matching your query!": [
+        ""
+      ],
+      "duplicated": [
+        ""
+      ],
+      "invalid format": [
+        ""
+      ],
+      "this value exceed the refundable amount": [
+        ""
+      ],
+      "date": [
+        ""
+      ],
+      "amount": [
+        ""
+      ],
+      "reason": [
+        ""
+      ],
+      "amount to be refunded": [
+        ""
+      ],
+      "Max refundable:": [
+        ""
+      ],
+      "Reason": [
+        ""
+      ],
+      "Choose one...": [
+        ""
+      ],
+      "requested by the customer": [
+        ""
+      ],
+      "other": [
+        ""
+      ],
+      "why this order is being refunded": [
+        ""
+      ],
+      "more information to give context": [
+        ""
+      ],
+      "Contract Terms": [
+        ""
+      ],
+      "human-readable description of the whole purchase": [
+        ""
+      ],
+      "total price for the transaction": [
+        ""
+      ],
+      "URL for this purchase": [
+        ""
+      ],
+      "Max fee": [
+        ""
+      ],
+      "maximum total deposit fee accepted by the merchant for this contract": [
+        ""
+      ],
+      "Max wire fee": [
+        ""
+      ],
+      "maximum wire fee accepted by the merchant": [
+        ""
+      ],
+      "over how many customer transactions does the merchant expect to 
amortize wire fees on average": [
+        ""
+      ],
+      "Created at": [
+        ""
+      ],
+      "time when this contract was generated": [
+        ""
+      ],
+      "after this deadline has passed no refunds will be accepted": [
+        ""
+      ],
+      "after this deadline, the merchant won't accept payments for the 
contract": [
+        ""
+      ],
+      "transfer deadline for the exchange": [
+        ""
+      ],
+      "time indicating when the order should be delivered": [
+        ""
+      ],
+      "where the order will be delivered": [
+        ""
+      ],
+      "Auto-refund delay": [
+        ""
+      ],
+      "how long the wallet should try to get an automatic refund for the 
purchase": [
+        ""
+      ],
+      "Extra info": [
+        ""
+      ],
+      "extra data that is only interpreted by the merchant frontend": [
+        ""
+      ],
+      "Order": [
+        ""
+      ],
+      "claimed": [
+        ""
+      ],
+      "claimed at": [
+        ""
+      ],
+      "Timeline": [
+        ""
+      ],
+      "Payment details": [
+        ""
+      ],
+      "Order status": [
+        ""
+      ],
+      "Product list": [
+        ""
+      ],
+      "paid": [
+        ""
+      ],
+      "wired": [
+        ""
+      ],
+      "refunded": [
+        ""
+      ],
+      "refund order": [
+        ""
+      ],
+      "not refundable": [
+        ""
+      ],
+      "refund": [
+        ""
+      ],
+      "Refunded amount": [
+        ""
+      ],
+      "Refund taken": [
+        ""
+      ],
+      "Status URL": [
+        ""
+      ],
+      "Refund URI": [
+        ""
+      ],
+      "unpaid": [
+        ""
+      ],
+      "pay at": [
+        ""
+      ],
+      "created at": [
+        ""
+      ],
+      "Order status URL": [
+        ""
+      ],
+      "Payment URI": [
+        ""
+      ],
+      "Unknown order status. This is an error, please contact the 
administrator.": [
+        ""
+      ],
+      "Back": [
+        ""
+      ],
+      "refund created successfully": [
+        ""
+      ],
+      "could not create the refund": [
+        ""
+      ],
+      "select date to show nearby orders": [
+        ""
+      ],
+      "order id": [
+        ""
+      ],
+      "jump to order with the given order ID": [
+        ""
+      ],
+      "remove all filters": [
+        ""
+      ],
+      "only show paid orders": [
+        ""
+      ],
+      "Paid": [
+        ""
+      ],
+      "only show orders with refunds": [
+        ""
+      ],
+      "Refunded": [
+        ""
+      ],
+      "only show orders where customers paid, but wire payments from payment 
provider are still pending": [
+        ""
+      ],
+      "Not wired": [
+        ""
+      ],
+      "clear date filter": [
+        ""
+      ],
+      "date (YYYY/MM/DD)": [
+        ""
+      ],
+      "Enter an order id": [
+        ""
+      ],
+      "order not found": [
+        ""
+      ],
+      "could not get the order to refund": [
+        ""
+      ],
+      "Loading...": [
+        ""
+      ],
+      "click here to configure the stock of the product, leave it as is and 
the backend will not control stock": [
+        ""
+      ],
+      "Manage stock": [
+        ""
+      ],
+      "this product has been configured without stock control": [
+        ""
+      ],
+      "Infinite": [
+        ""
+      ],
+      "lost cannot be greater than current and incoming (max %1$s)": [
+        ""
+      ],
+      "Incoming": [
+        ""
+      ],
+      "Lost": [
+        ""
+      ],
+      "Current": [
+        ""
+      ],
+      "remove stock control for this product": [
+        ""
+      ],
+      "without stock": [
+        ""
+      ],
+      "Next restock": [
+        ""
+      ],
+      "Delivery address": [
+        ""
+      ],
+      "product identification to use in URLs (for internal use only)": [
+        ""
+      ],
+      "illustration of the product for customers": [
+        ""
+      ],
+      "product description for customers": [
+        ""
+      ],
+      "Age restricted": [
+        ""
+      ],
+      "is this product restricted for customer below certain age?": [
+        ""
+      ],
+      "unit describing quantity of product sold (e.g. 2 kilograms, 5 liters, 3 
items, 5 meters) for customers": [
+        ""
+      ],
+      "sale price for customers, including taxes, for above units of the 
product": [
+        ""
+      ],
+      "Stock": [
+        ""
+      ],
+      "product inventory for products with finite supply (for internal use 
only)": [
+        ""
+      ],
+      "taxes included in the product price, exposed to customers": [
+        ""
+      ],
+      "Need to complete marked fields": [
+        ""
+      ],
+      "could not create product": [
+        ""
+      ],
+      "Products": [
+        ""
+      ],
+      "add product to inventory": [
+        ""
+      ],
+      "Sell": [
+        ""
+      ],
+      "Profit": [
+        ""
+      ],
+      "Sold": [
+        ""
+      ],
+      "free": [
+        ""
+      ],
+      "go to product update page": [
+        ""
+      ],
+      "Update": [
+        ""
+      ],
+      "remove this product from the database": [
+        ""
+      ],
+      "update the product with new price": [
+        ""
+      ],
+      "update product with new price": [
+        ""
+      ],
+      "add more elements to the inventory": [
+        ""
+      ],
+      "report elements lost in the inventory": [
+        ""
+      ],
+      "new price for the product": [
+        ""
+      ],
+      "the are value with errors": [
+        ""
+      ],
+      "update product with new stock and price": [
+        ""
+      ],
+      "There is no products yet, add more pressing the + sign": [
+        ""
+      ],
+      "product updated successfully": [
+        ""
+      ],
+      "could not update the product": [
+        ""
+      ],
+      "product delete successfully": [
+        ""
+      ],
+      "could not delete the product": [
+        ""
+      ],
+      "Product id:": [
+        ""
+      ],
+      "To complete the setup of the reserve, you must now initiate a wire 
transfer using the given wire transfer subject and crediting the specified 
amount to the indicated account of the exchange.": [
+        ""
+      ],
+      "If your system supports RFC 8905, you can do this by opening this 
URI:": [
+        ""
+      ],
+      "it should be greater than 0": [
+        ""
+      ],
+      "must be a valid URL": [
+        ""
+      ],
+      "Initial balance": [
+        ""
+      ],
+      "balance prior to deposit": [
+        ""
+      ],
+      "Exchange URL": [
+        ""
+      ],
+      "URL of exchange": [
+        ""
+      ],
+      "Next": [
+        ""
+      ],
+      "Wire method": [
+        ""
+      ],
+      "method to use for wire transfer": [
+        ""
+      ],
+      "Select one wire method": [
+        ""
+      ],
+      "could not create reserve": [
+        ""
+      ],
+      "Valid until": [
+        ""
+      ],
+      "Created balance": [
+        ""
+      ],
+      "Exchange balance": [
+        ""
+      ],
+      "Picked up": [
+        ""
+      ],
+      "Committed": [
+        ""
+      ],
+      "Account address": [
+        ""
+      ],
+      "Subject": [
+        ""
+      ],
+      "Tips": [
+        ""
+      ],
+      "No tips has been authorized from this reserve": [
+        ""
+      ],
+      "Authorized": [
+        ""
+      ],
+      "Expiration": [
+        ""
+      ],
+      "amount of tip": [
+        ""
+      ],
+      "Justification": [
+        ""
+      ],
+      "reason for the tip": [
+        ""
+      ],
+      "URL after tip": [
+        ""
+      ],
+      "URL to visit after tip payment": [
+        ""
+      ],
+      "Reserves not yet funded": [
+        ""
+      ],
+      "Reserves ready": [
+        ""
+      ],
+      "add new reserve": [
+        ""
+      ],
+      "Expires at": [
+        ""
+      ],
+      "Initial": [
+        ""
+      ],
+      "delete selected reserve from the database": [
+        ""
+      ],
+      "authorize new tip from selected reserve": [
+        ""
+      ],
+      "There is no ready reserves yet, add more pressing the + sign or fund 
them": [
+        ""
+      ],
+      "Expected Balance": [
+        ""
+      ],
+      "could not create the tip": [
+        ""
+      ],
+      "should not be empty": [
+        ""
+      ],
+      "should be greater that 0": [
+        ""
+      ],
+      "can't be empty": [
+        ""
+      ],
+      "to short": [
+        ""
+      ],
+      "just letters and numbers from 2 to 7": [
+        ""
+      ],
+      "size of the key should be 32": [
+        ""
+      ],
+      "Identifier": [
+        ""
+      ],
+      "Name of the template in URLs.": [
+        ""
+      ],
+      "Describe what this template stands for": [
+        ""
+      ],
+      "Fixed summary": [
+        ""
+      ],
+      "If specified, this template will create order with the same summary": [
+        ""
+      ],
+      "Fixed price": [
+        ""
+      ],
+      "If specified, this template will create order with the same price": [
+        ""
+      ],
+      "Minimum age": [
+        ""
+      ],
+      "Is this contract restricted to some age?": [
+        ""
+      ],
+      "Payment timeout": [
+        ""
+      ],
+      "How much time has the customer to complete the payment once the order 
was created.": [
+        ""
+      ],
+      "Verification algorithm": [
+        ""
+      ],
+      "Algorithm to use to verify transaction in offline mode": [
+        ""
+      ],
+      "Point-of-sale key": [
+        ""
+      ],
+      "Useful to validate the purchase": [
+        ""
+      ],
+      "generate random secret key": [
+        ""
+      ],
+      "random": [
+        ""
+      ],
+      "show secret key": [
+        ""
+      ],
+      "hide secret key": [
+        ""
+      ],
+      "hide": [
+        ""
+      ],
+      "show": [
+        ""
+      ],
+      "could not inform template": [
+        ""
+      ],
+      "Amount is required": [
+        ""
+      ],
+      "Order summary is required": [
+        ""
+      ],
+      "New order for template": [
+        ""
+      ],
+      "Amount of the order": [
+        ""
+      ],
+      "Order summary": [
+        ""
+      ],
+      "could not create order from template": [
+        ""
+      ],
+      "Here you can specify a default value for fields that are not fixed. 
Default values can be edited by the customer before the payment.": [
+        ""
+      ],
+      "Fixed amount": [
+        ""
+      ],
+      "Default amount": [
+        ""
+      ],
+      "Default summary": [
+        ""
+      ],
+      "Print": [
+        ""
+      ],
+      "Setup TOTP": [
+        ""
+      ],
+      "Templates": [
+        ""
+      ],
+      "add new templates": [
+        ""
+      ],
+      "load more templates before the first one": [
+        ""
+      ],
+      "load newer templates": [
+        ""
+      ],
+      "delete selected templates from the database": [
+        ""
+      ],
+      "use template to create new order": [
+        ""
+      ],
+      "create qr code for the template": [
+        ""
+      ],
+      "load more templates after the last one": [
+        ""
+      ],
+      "load older templates": [
+        ""
+      ],
+      "There is no templates yet, add more pressing the + sign": [
+        ""
+      ],
+      "template delete successfully": [
+        ""
+      ],
+      "could not delete the template": [
+        ""
+      ],
+      "could not update template": [
+        ""
+      ],
+      "should be one of '%1$s'": [
+        ""
+      ],
+      "Webhook ID to use": [
+        ""
+      ],
+      "Event": [
+        ""
+      ],
+      "The event of the webhook: why the webhook is used": [
+        ""
+      ],
+      "Method": [
+        ""
+      ],
+      "Method used by the webhook": [
+        ""
+      ],
+      "URL": [
+        ""
+      ],
+      "URL of the webhook where the customer will be redirected": [
+        ""
+      ],
+      "Header": [
+        ""
+      ],
+      "Header template of the webhook": [
+        ""
+      ],
+      "Body": [
+        ""
+      ],
+      "Body template by the webhook": [
+        ""
+      ],
+      "Webhooks": [
+        ""
+      ],
+      "add new webhooks": [
+        ""
+      ],
+      "load more webhooks before the first one": [
+        ""
+      ],
+      "load newer webhooks": [
+        ""
+      ],
+      "Event type": [
+        ""
+      ],
+      "delete selected webhook from the database": [
+        ""
+      ],
+      "load more webhooks after the last one": [
+        ""
+      ],
+      "load older webhooks": [
+        ""
+      ],
+      "There is no webhooks yet, add more pressing the + sign": [
+        ""
+      ],
+      "webhook delete successfully": [
+        ""
+      ],
+      "could not delete the webhook": [
+        ""
+      ],
+      "check the id, does not look valid": [
+        ""
+      ],
+      "should have 52 characters, current %1$s": [
+        ""
+      ],
+      "URL doesn't have the right format": [
+        ""
+      ],
+      "Credited bank account": [
+        ""
+      ],
+      "Select one account": [
+        ""
+      ],
+      "Bank account of the merchant where the payment was received": [
+        ""
+      ],
+      "Wire transfer ID": [
+        ""
+      ],
+      "unique identifier of the wire transfer used by the exchange, must be 52 
characters long": [
+        ""
+      ],
+      "Base URL of the exchange that made the transfer, should have been in 
the wire transfer subject": [
+        ""
+      ],
+      "Amount credited": [
+        ""
+      ],
+      "Actual amount that was wired to the merchant's bank account": [
+        ""
+      ],
+      "could not inform transfer": [
+        ""
+      ],
+      "Transfers": [
+        ""
+      ],
+      "add new transfer": [
+        ""
+      ],
+      "load more transfers before the first one": [
+        ""
+      ],
+      "load newer transfers": [
+        ""
+      ],
+      "Credit": [
+        ""
+      ],
+      "Confirmed": [
+        ""
+      ],
+      "Verified": [
+        ""
+      ],
+      "Executed at": [
+        ""
+      ],
+      "yes": [
+        ""
+      ],
+      "no": [
+        ""
+      ],
+      "unknown": [
+        ""
+      ],
+      "delete selected transfer from the database": [
+        ""
+      ],
+      "load more transfer after the last one": [
+        ""
+      ],
+      "load older transfers": [
+        ""
+      ],
+      "There is no transfer yet, add more pressing the + sign": [
+        ""
+      ],
+      "filter by account address": [
+        ""
+      ],
+      "only show wire transfers confirmed by the merchant": [
+        ""
+      ],
+      "only show wire transfers claimed by the exchange": [
+        ""
+      ],
+      "Unverified": [
+        ""
+      ],
+      "is not valid": [
+        ""
+      ],
+      "is not a number": [
+        ""
+      ],
+      "must be 1 or greater": [
+        ""
+      ],
+      "max 7 lines": [
+        ""
+      ],
+      "change authorization configuration": [
+        ""
+      ],
+      "Need to complete marked fields and choose authorization method": [
+        ""
+      ],
+      "This is not a valid bitcoin address.": [
+        ""
+      ],
+      "This is not a valid Ethereum address.": [
+        ""
+      ],
+      "IBAN numbers usually have more that 4 digits": [
+        ""
+      ],
+      "IBAN numbers usually have less that 34 digits": [
+        ""
+      ],
+      "IBAN country code not found": [
+        ""
+      ],
+      "IBAN number is not valid, checksum is wrong": [
+        ""
+      ],
+      "Target type": [
+        ""
+      ],
+      "Method to use for wire transfer": [
+        ""
+      ],
+      "Routing": [
+        ""
+      ],
+      "Routing number.": [
+        ""
+      ],
+      "Account": [
+        ""
+      ],
+      "Account number.": [
+        ""
+      ],
+      "Business Identifier Code.": [
+        ""
+      ],
+      "Bank Account Number.": [
+        ""
+      ],
+      "Unified Payment Interface.": [
+        ""
+      ],
+      "Bitcoin protocol.": [
+        ""
+      ],
+      "Ethereum protocol.": [
+        ""
+      ],
+      "Interledger protocol.": [
+        ""
+      ],
+      "Host": [
+        ""
+      ],
+      "Bank host.": [
+        ""
+      ],
+      "Bank account.": [
+        ""
+      ],
+      "Bank account owner's name.": [
+        ""
+      ],
+      "No accounts yet.": [
+        ""
+      ],
+      "Name of the instance in URLs. The 'default' instance is special in that 
it is used to administer other instances.": [
+        ""
+      ],
+      "Business name": [
+        ""
+      ],
+      "Legal name of the business represented by this instance.": [
+        ""
+      ],
+      "Email": [
+        ""
+      ],
+      "Contact email": [
+        ""
+      ],
+      "Website URL": [
+        ""
+      ],
+      "URL.": [
+        ""
+      ],
+      "Logo": [
+        ""
+      ],
+      "Logo image.": [
+        ""
+      ],
+      "Bank account": [
+        ""
+      ],
+      "URI specifying bank account for crediting revenue.": [
+        ""
+      ],
+      "Default max deposit fee": [
+        ""
+      ],
+      "Maximum deposit fees this merchant is willing to pay per order by 
default.": [
+        ""
+      ],
+      "Default max wire fee": [
+        ""
+      ],
+      "Maximum wire fees this merchant is willing to pay per wire transfer by 
default.": [
+        ""
+      ],
+      "Default wire fee amortization": [
+        ""
+      ],
+      "Number of orders excess wire transfer fees will be divided by to 
compute per order surcharge.": [
+        ""
+      ],
+      "Physical location of the merchant.": [
+        ""
+      ],
+      "Jurisdiction": [
+        ""
+      ],
+      "Jurisdiction for legal disputes with the merchant.": [
+        ""
+      ],
+      "Default payment delay": [
+        ""
+      ],
+      "Time customers have to pay an order before the offer expires by 
default.": [
+        ""
+      ],
+      "Default wire transfer delay": [
+        ""
+      ],
+      "Maximum time an exchange is allowed to delay wiring funds to the 
merchant, enabling it to aggregate smaller payments into larger wire transfers 
and reducing wire fees.": [
+        ""
+      ],
+      "Instance id": [
+        ""
+      ],
+      "Change the authorization method use for this instance.": [
+        ""
+      ],
+      "Manage access token": [
+        ""
+      ],
+      "Failed to create instance": [
+        ""
+      ],
+      "Login required": [
+        ""
+      ],
+      "Please enter your access token.": [
+        ""
+      ],
+      "Access Token": [
+        ""
+      ],
+      "The request to the backend take too long and was cancelled": [
+        ""
+      ],
+      "Diagnostic from %1$s is \"%2$s\"": [
+        ""
+      ],
+      "The backend reported a problem: HTTP status #%1$s": [
+        ""
+      ],
+      "Diagnostic from %1$s is '%2$s'": [
+        ""
+      ],
+      "Access denied": [
+        ""
+      ],
+      "The access token provided is invalid.": [
+        ""
+      ],
+      "No 'default' instance configured yet.": [
+        ""
+      ],
+      "Create a 'default' instance to begin using the merchant backoffice.": [
+        ""
+      ],
+      "The access token provided is invalid": [
+        ""
+      ],
+      "Hide for today": [
+        ""
+      ],
+      "Instance": [
+        ""
+      ],
+      "Settings": [
+        ""
+      ],
+      "Connection": [
+        ""
+      ],
+      "New": [
+        ""
+      ],
+      "List": [
+        ""
+      ],
+      "Log out": [
+        ""
+      ],
+      "Check your token is valid": [
+        ""
+      ],
+      "Couldn't access the server.": [
+        ""
+      ],
+      "Could not infer instance id from url %1$s": [
+        ""
+      ],
+      "Server not found": [
+        ""
+      ],
+      "Server response with an error code": [
+        ""
+      ],
+      "Got message %1$s from %2$s": [
+        ""
+      ],
+      "Response from server is unreadable, http status: %1$s": [
+        ""
+      ],
+      "Unexpected Error": [
+        ""
+      ],
+      "The value %1$s is invalid for a payment url": [
+        ""
+      ],
+      "add element to the list": [
+        ""
+      ],
+      "add": [
+        ""
+      ],
+      "Deleting": [
+        ""
+      ],
+      "Changing": [
+        ""
+      ],
+      "Order ID": [
+        ""
+      ],
+      "Payment URL": [
+        ""
+      ]
+    }
+  }
+};
+
+strings['en'] = {
+  "domain": "messages",
+  "locale_data": {
+    "messages": {
+      "": {
+        "domain": "messages",
+        "plural_forms": "nplurals=2; plural=(n != 1);",
+        "lang": ""
+      },
+      "Cancel": [
+        ""
+      ],
+      "%1$s": [
+        ""
+      ],
+      "Close": [
+        ""
+      ],
+      "Continue": [
+        ""
+      ],
+      "Clear": [
+        ""
+      ],
+      "Confirm": [
+        ""
+      ],
+      "is not the same as the current access token": [
+        ""
+      ],
+      "cannot be empty": [
+        ""
+      ],
+      "cannot be the same as the old token": [
+        ""
+      ],
+      "is not the same": [
+        ""
+      ],
+      "You are updating the access token from instance with id %1$s": [
+        ""
+      ],
+      "Old access token": [
+        ""
+      ],
+      "access token currently in use": [
+        ""
+      ],
+      "New access token": [
+        ""
+      ],
+      "next access token to be used": [
+        ""
+      ],
+      "Repeat access token": [
+        ""
+      ],
+      "confirm the same access token": [
+        ""
+      ],
+      "Clearing the access token will mean public access to the instance": [
+        ""
+      ],
+      "cannot be the same as the old access token": [
+        ""
+      ],
+      "You are setting the access token for the new instance": [
+        ""
+      ],
+      "With external authorization method no check will be done by the 
merchant backend": [
+        ""
+      ],
+      "Set external authorization": [
+        ""
+      ],
+      "Set access token": [
+        ""
+      ],
+      "Operation in progress...": [
+        ""
+      ],
+      "The operation will be automatically canceled after %1$s seconds": [
+        ""
+      ],
+      "Instances": [
+        ""
+      ],
+      "Delete": [
+        ""
+      ],
+      "add new instance": [
+        ""
+      ],
+      "ID": [
+        ""
+      ],
+      "Name": [
+        ""
+      ],
+      "Edit": [
+        ""
+      ],
+      "Purge": [
+        ""
+      ],
+      "There is no instances yet, add more pressing the + sign": [
+        ""
+      ],
+      "Only show active instances": [
+        ""
+      ],
+      "Active": [
+        ""
+      ],
+      "Only show deleted instances": [
+        ""
+      ],
+      "Deleted": [
+        ""
+      ],
+      "Show all instances": [
+        ""
+      ],
+      "All": [
+        ""
+      ],
+      "Instance \"%1$s\" (ID: %2$s) has been deleted": [
+        ""
+      ],
+      "Failed to delete instance": [
+        ""
+      ],
+      "Instance '%1$s' (ID: %2$s) has been disabled": [
+        ""
+      ],
+      "Failed to purge instance": [
+        ""
+      ],
+      "Pending KYC verification": [
+        ""
+      ],
+      "Timed out": [
+        ""
+      ],
+      "Exchange": [
+        ""
+      ],
+      "Target account": [
+        ""
+      ],
+      "KYC URL": [
+        ""
+      ],
+      "Code": [
+        ""
+      ],
+      "Http Status": [
+        ""
+      ],
+      "No pending kyc verification!": [
+        ""
+      ],
+      "change value to unknown date": [
+        ""
+      ],
+      "change value to empty": [
+        ""
+      ],
+      "clear": [
+        ""
+      ],
+      "change value to never": [
+        ""
+      ],
+      "never": [
+        ""
+      ],
+      "Country": [
+        ""
+      ],
+      "Address": [
+        ""
+      ],
+      "Building number": [
+        ""
+      ],
+      "Building name": [
+        ""
+      ],
+      "Street": [
+        ""
+      ],
+      "Post code": [
+        ""
+      ],
+      "Town location": [
+        ""
+      ],
+      "Town": [
+        ""
+      ],
+      "District": [
+        ""
+      ],
+      "Country subdivision": [
+        ""
+      ],
+      "Product id": [
+        ""
+      ],
+      "Description": [
+        ""
+      ],
+      "Product": [
+        ""
+      ],
+      "search products by it's description or id": [
+        ""
+      ],
+      "no products found with that description": [
+        ""
+      ],
+      "You must enter a valid product identifier.": [
+        ""
+      ],
+      "Quantity must be greater than 0!": [
+        ""
+      ],
+      "This quantity exceeds remaining stock. Currently, only %1$s units 
remain unreserved in stock.": [
+        ""
+      ],
+      "Quantity": [
+        ""
+      ],
+      "how many products will be added": [
+        ""
+      ],
+      "Add from inventory": [
+        ""
+      ],
+      "Image should be smaller than 1 MB": [
+        ""
+      ],
+      "Add": [
+        ""
+      ],
+      "Remove": [
+        ""
+      ],
+      "No taxes configured for this product.": [
+        ""
+      ],
+      "Amount": [
+        ""
+      ],
+      "Taxes can be in currencies that differ from the main currency used by 
the merchant.": [
+        ""
+      ],
+      "Enter currency and value separated with a colon, e.g. 
&quot;USD:2.3&quot;.": [
+        ""
+      ],
+      "Legal name of the tax, e.g. VAT or import duties.": [
+        ""
+      ],
+      "add tax to the tax list": [
+        ""
+      ],
+      "describe and add a product that is not in the inventory list": [
+        ""
+      ],
+      "Add custom product": [
+        ""
+      ],
+      "Complete information of the product": [
+        ""
+      ],
+      "Image": [
+        ""
+      ],
+      "photo of the product": [
+        ""
+      ],
+      "full product description": [
+        ""
+      ],
+      "Unit": [
+        ""
+      ],
+      "name of the product unit": [
+        ""
+      ],
+      "Price": [
+        ""
+      ],
+      "amount in the current currency": [
+        ""
+      ],
+      "Taxes": [
+        ""
+      ],
+      "image": [
+        ""
+      ],
+      "description": [
+        ""
+      ],
+      "quantity": [
+        ""
+      ],
+      "unit price": [
+        ""
+      ],
+      "total price": [
+        ""
+      ],
+      "required": [
+        ""
+      ],
+      "not valid": [
+        ""
+      ],
+      "must be greater than 0": [
+        ""
+      ],
+      "not a valid json": [
+        ""
+      ],
+      "should be in the future": [
+        ""
+      ],
+      "refund deadline cannot be before pay deadline": [
+        ""
+      ],
+      "wire transfer deadline cannot be before refund deadline": [
+        ""
+      ],
+      "wire transfer deadline cannot be before pay deadline": [
+        ""
+      ],
+      "should have a refund deadline": [
+        ""
+      ],
+      "auto refund cannot be after refund deadline": [
+        ""
+      ],
+      "Manage products in order": [
+        ""
+      ],
+      "Manage list of products in the order.": [
+        ""
+      ],
+      "Remove this product from the order.": [
+        ""
+      ],
+      "Total price": [
+        ""
+      ],
+      "total product price added up": [
+        ""
+      ],
+      "Amount to be paid by the customer": [
+        ""
+      ],
+      "Order price": [
+        ""
+      ],
+      "final order price": [
+        ""
+      ],
+      "Summary": [
+        ""
+      ],
+      "Title of the order to be shown to the customer": [
+        ""
+      ],
+      "Shipping and Fulfillment": [
+        ""
+      ],
+      "Delivery date": [
+        ""
+      ],
+      "Deadline for physical delivery assured by the merchant.": [
+        ""
+      ],
+      "Location": [
+        ""
+      ],
+      "address where the products will be delivered": [
+        ""
+      ],
+      "Fulfillment URL": [
+        ""
+      ],
+      "URL to which the user will be redirected after successful payment.": [
+        ""
+      ],
+      "Taler payment options": [
+        ""
+      ],
+      "Override default Taler payment settings for this order": [
+        ""
+      ],
+      "Payment deadline": [
+        ""
+      ],
+      "Deadline for the customer to pay for the offer before it expires. 
Inventory products will be reserved until this deadline.": [
+        ""
+      ],
+      "Refund deadline": [
+        ""
+      ],
+      "Time until which the order can be refunded by the merchant.": [
+        ""
+      ],
+      "Wire transfer deadline": [
+        ""
+      ],
+      "Deadline for the exchange to make the wire transfer.": [
+        ""
+      ],
+      "Auto-refund deadline": [
+        ""
+      ],
+      "Time until which the wallet will automatically check for refunds 
without user interaction.": [
+        ""
+      ],
+      "Maximum deposit fee": [
+        ""
+      ],
+      "Maximum deposit fees the merchant is willing to cover for this order. 
Higher deposit fees must be covered in full by the consumer.": [
+        ""
+      ],
+      "Maximum wire fee": [
+        ""
+      ],
+      "Maximum aggregate wire fees the merchant is willing to cover for this 
order. Wire fees exceeding this amount are to be covered by the customers.": [
+        ""
+      ],
+      "Wire fee amortization": [
+        ""
+      ],
+      "Factor by which wire fees exceeding the above threshold are divided to 
determine the share of excess wire fees to be paid explicitly by the 
consumer.": [
+        ""
+      ],
+      "Create token": [
+        ""
+      ],
+      "Uncheck this option if the merchant backend generated an order ID with 
enough entropy to prevent adversarial claims.": [
+        ""
+      ],
+      "Minimum age required": [
+        ""
+      ],
+      "Any value greater than 0 will limit the coins able be used to pay this 
contract. If empty the age restriction will be defined by the products": [
+        ""
+      ],
+      "Min age defined by the producs is %1$s": [
+        ""
+      ],
+      "Additional information": [
+        ""
+      ],
+      "Custom information to be included in the contract for this order.": [
+        ""
+      ],
+      "You must enter a value in JavaScript Object Notation (JSON).": [
+        ""
+      ],
+      "days": [
+        ""
+      ],
+      "hours": [
+        ""
+      ],
+      "minutes": [
+        ""
+      ],
+      "seconds": [
+        ""
+      ],
+      "forever": [
+        ""
+      ],
+      "%1$sM": [
+        ""
+      ],
+      "%1$sY": [
+        ""
+      ],
+      "%1$sd": [
+        ""
+      ],
+      "%1$sh": [
+        ""
+      ],
+      "%1$smin": [
+        ""
+      ],
+      "%1$ssec": [
+        ""
+      ],
+      "Orders": [
+        ""
+      ],
+      "create order": [
+        ""
+      ],
+      "load newer orders": [
+        ""
+      ],
+      "Date": [
+        ""
+      ],
+      "Refund": [
+        ""
+      ],
+      "copy url": [
+        ""
+      ],
+      "load older orders": [
+        ""
+      ],
+      "No orders have been found matching your query!": [
+        ""
+      ],
+      "duplicated": [
+        ""
+      ],
+      "invalid format": [
+        ""
+      ],
+      "this value exceed the refundable amount": [
+        ""
+      ],
+      "date": [
+        ""
+      ],
+      "amount": [
+        ""
+      ],
+      "reason": [
+        ""
+      ],
+      "amount to be refunded": [
+        ""
+      ],
+      "Max refundable:": [
+        ""
+      ],
+      "Reason": [
+        ""
+      ],
+      "Choose one...": [
+        ""
+      ],
+      "requested by the customer": [
+        ""
+      ],
+      "other": [
+        ""
+      ],
+      "why this order is being refunded": [
+        ""
+      ],
+      "more information to give context": [
+        ""
+      ],
+      "Contract Terms": [
+        ""
+      ],
+      "human-readable description of the whole purchase": [
+        ""
+      ],
+      "total price for the transaction": [
+        ""
+      ],
+      "URL for this purchase": [
+        ""
+      ],
+      "Max fee": [
+        ""
+      ],
+      "maximum total deposit fee accepted by the merchant for this contract": [
+        ""
+      ],
+      "Max wire fee": [
+        ""
+      ],
+      "maximum wire fee accepted by the merchant": [
+        ""
+      ],
+      "over how many customer transactions does the merchant expect to 
amortize wire fees on average": [
+        ""
+      ],
+      "Created at": [
+        ""
+      ],
+      "time when this contract was generated": [
+        ""
+      ],
+      "after this deadline has passed no refunds will be accepted": [
+        ""
+      ],
+      "after this deadline, the merchant won't accept payments for the 
contract": [
+        ""
+      ],
+      "transfer deadline for the exchange": [
+        ""
+      ],
+      "time indicating when the order should be delivered": [
+        ""
+      ],
+      "where the order will be delivered": [
+        ""
+      ],
+      "Auto-refund delay": [
+        ""
+      ],
+      "how long the wallet should try to get an automatic refund for the 
purchase": [
+        ""
+      ],
+      "Extra info": [
+        ""
+      ],
+      "extra data that is only interpreted by the merchant frontend": [
+        ""
+      ],
+      "Order": [
+        ""
+      ],
+      "claimed": [
+        ""
+      ],
+      "claimed at": [
+        ""
+      ],
+      "Timeline": [
+        ""
+      ],
+      "Payment details": [
+        ""
+      ],
+      "Order status": [
+        ""
+      ],
+      "Product list": [
+        ""
+      ],
+      "paid": [
+        ""
+      ],
+      "wired": [
+        ""
+      ],
+      "refunded": [
+        ""
+      ],
+      "refund order": [
+        ""
+      ],
+      "not refundable": [
+        ""
+      ],
+      "refund": [
+        ""
+      ],
+      "Refunded amount": [
+        ""
+      ],
+      "Refund taken": [
+        ""
+      ],
+      "Status URL": [
+        ""
+      ],
+      "Refund URI": [
+        ""
+      ],
+      "unpaid": [
+        ""
+      ],
+      "pay at": [
+        ""
+      ],
+      "created at": [
+        ""
+      ],
+      "Order status URL": [
+        ""
+      ],
+      "Payment URI": [
+        ""
+      ],
+      "Unknown order status. This is an error, please contact the 
administrator.": [
+        ""
+      ],
+      "Back": [
+        ""
+      ],
+      "refund created successfully": [
+        ""
+      ],
+      "could not create the refund": [
+        ""
+      ],
+      "select date to show nearby orders": [
+        ""
+      ],
+      "order id": [
+        ""
+      ],
+      "jump to order with the given order ID": [
+        ""
+      ],
+      "remove all filters": [
+        ""
+      ],
+      "only show paid orders": [
+        ""
+      ],
+      "Paid": [
+        ""
+      ],
+      "only show orders with refunds": [
+        ""
+      ],
+      "Refunded": [
+        ""
+      ],
+      "only show orders where customers paid, but wire payments from payment 
provider are still pending": [
+        ""
+      ],
+      "Not wired": [
+        ""
+      ],
+      "clear date filter": [
+        ""
+      ],
+      "date (YYYY/MM/DD)": [
+        ""
+      ],
+      "Enter an order id": [
+        ""
+      ],
+      "order not found": [
+        ""
+      ],
+      "could not get the order to refund": [
+        ""
+      ],
+      "Loading...": [
+        ""
+      ],
+      "click here to configure the stock of the product, leave it as is and 
the backend will not control stock": [
+        ""
+      ],
+      "Manage stock": [
+        ""
+      ],
+      "this product has been configured without stock control": [
+        ""
+      ],
+      "Infinite": [
+        ""
+      ],
+      "lost cannot be greater than current and incoming (max %1$s)": [
+        ""
+      ],
+      "Incoming": [
+        ""
+      ],
+      "Lost": [
+        ""
+      ],
+      "Current": [
+        ""
+      ],
+      "remove stock control for this product": [
+        ""
+      ],
+      "without stock": [
+        ""
+      ],
+      "Next restock": [
+        ""
+      ],
+      "Delivery address": [
+        ""
+      ],
+      "product identification to use in URLs (for internal use only)": [
+        ""
+      ],
+      "illustration of the product for customers": [
+        ""
+      ],
+      "product description for customers": [
+        ""
+      ],
+      "Age restricted": [
+        ""
+      ],
+      "is this product restricted for customer below certain age?": [
+        ""
+      ],
+      "unit describing quantity of product sold (e.g. 2 kilograms, 5 liters, 3 
items, 5 meters) for customers": [
+        ""
+      ],
+      "sale price for customers, including taxes, for above units of the 
product": [
+        ""
+      ],
+      "Stock": [
+        ""
+      ],
+      "product inventory for products with finite supply (for internal use 
only)": [
+        ""
+      ],
+      "taxes included in the product price, exposed to customers": [
+        ""
+      ],
+      "Need to complete marked fields": [
+        ""
+      ],
+      "could not create product": [
+        ""
+      ],
+      "Products": [
+        ""
+      ],
+      "add product to inventory": [
+        ""
+      ],
+      "Sell": [
+        ""
+      ],
+      "Profit": [
+        ""
+      ],
+      "Sold": [
+        ""
+      ],
+      "free": [
+        ""
+      ],
+      "go to product update page": [
+        ""
+      ],
+      "Update": [
+        ""
+      ],
+      "remove this product from the database": [
+        ""
+      ],
+      "update the product with new price": [
+        ""
+      ],
+      "update product with new price": [
+        ""
+      ],
+      "add more elements to the inventory": [
+        ""
+      ],
+      "report elements lost in the inventory": [
+        ""
+      ],
+      "new price for the product": [
+        ""
+      ],
+      "the are value with errors": [
+        ""
+      ],
+      "update product with new stock and price": [
+        ""
+      ],
+      "There is no products yet, add more pressing the + sign": [
+        ""
+      ],
+      "product updated successfully": [
+        ""
+      ],
+      "could not update the product": [
+        ""
+      ],
+      "product delete successfully": [
+        ""
+      ],
+      "could not delete the product": [
+        ""
+      ],
+      "Product id:": [
+        ""
+      ],
+      "To complete the setup of the reserve, you must now initiate a wire 
transfer using the given wire transfer subject and crediting the specified 
amount to the indicated account of the exchange.": [
+        ""
+      ],
+      "If your system supports RFC 8905, you can do this by opening this 
URI:": [
+        ""
+      ],
+      "it should be greater than 0": [
+        ""
+      ],
+      "must be a valid URL": [
+        ""
+      ],
+      "Initial balance": [
+        ""
+      ],
+      "balance prior to deposit": [
+        ""
+      ],
+      "Exchange URL": [
+        ""
+      ],
+      "URL of exchange": [
+        ""
+      ],
+      "Next": [
+        ""
+      ],
+      "Wire method": [
+        ""
+      ],
+      "method to use for wire transfer": [
+        ""
+      ],
+      "Select one wire method": [
+        ""
+      ],
+      "could not create reserve": [
+        ""
+      ],
+      "Valid until": [
+        ""
+      ],
+      "Created balance": [
+        ""
+      ],
+      "Exchange balance": [
+        ""
+      ],
+      "Picked up": [
+        ""
+      ],
+      "Committed": [
+        ""
+      ],
+      "Account address": [
+        ""
+      ],
+      "Subject": [
+        ""
+      ],
+      "Tips": [
+        ""
+      ],
+      "No tips has been authorized from this reserve": [
+        ""
+      ],
+      "Authorized": [
+        ""
+      ],
+      "Expiration": [
+        ""
+      ],
+      "amount of tip": [
+        ""
+      ],
+      "Justification": [
+        ""
+      ],
+      "reason for the tip": [
+        ""
+      ],
+      "URL after tip": [
+        ""
+      ],
+      "URL to visit after tip payment": [
+        ""
+      ],
+      "Reserves not yet funded": [
+        ""
+      ],
+      "Reserves ready": [
+        ""
+      ],
+      "add new reserve": [
+        ""
+      ],
+      "Expires at": [
+        ""
+      ],
+      "Initial": [
+        ""
+      ],
+      "delete selected reserve from the database": [
+        ""
+      ],
+      "authorize new tip from selected reserve": [
+        ""
+      ],
+      "There is no ready reserves yet, add more pressing the + sign or fund 
them": [
+        ""
+      ],
+      "Expected Balance": [
+        ""
+      ],
+      "could not create the tip": [
+        ""
+      ],
+      "should not be empty": [
+        ""
+      ],
+      "should be greater that 0": [
+        ""
+      ],
+      "can't be empty": [
+        ""
+      ],
+      "to short": [
+        ""
+      ],
+      "just letters and numbers from 2 to 7": [
+        ""
+      ],
+      "size of the key should be 32": [
+        ""
+      ],
+      "Identifier": [
+        ""
+      ],
+      "Name of the template in URLs.": [
+        ""
+      ],
+      "Describe what this template stands for": [
+        ""
+      ],
+      "Fixed summary": [
+        ""
+      ],
+      "If specified, this template will create order with the same summary": [
+        ""
+      ],
+      "Fixed price": [
+        ""
+      ],
+      "If specified, this template will create order with the same price": [
+        ""
+      ],
+      "Minimum age": [
+        ""
+      ],
+      "Is this contract restricted to some age?": [
+        ""
+      ],
+      "Payment timeout": [
+        ""
+      ],
+      "How much time has the customer to complete the payment once the order 
was created.": [
+        ""
+      ],
+      "Verification algorithm": [
+        ""
+      ],
+      "Algorithm to use to verify transaction in offline mode": [
+        ""
+      ],
+      "Point-of-sale key": [
+        ""
+      ],
+      "Useful to validate the purchase": [
+        ""
+      ],
+      "generate random secret key": [
+        ""
+      ],
+      "random": [
+        ""
+      ],
+      "show secret key": [
+        ""
+      ],
+      "hide secret key": [
+        ""
+      ],
+      "hide": [
+        ""
+      ],
+      "show": [
+        ""
+      ],
+      "could not inform template": [
+        ""
+      ],
+      "Amount is required": [
+        ""
+      ],
+      "Order summary is required": [
+        ""
+      ],
+      "New order for template": [
+        ""
+      ],
+      "Amount of the order": [
+        ""
+      ],
+      "Order summary": [
+        ""
+      ],
+      "could not create order from template": [
+        ""
+      ],
+      "Here you can specify a default value for fields that are not fixed. 
Default values can be edited by the customer before the payment.": [
+        ""
+      ],
+      "Fixed amount": [
+        ""
+      ],
+      "Default amount": [
+        ""
+      ],
+      "Default summary": [
+        ""
+      ],
+      "Print": [
+        ""
+      ],
+      "Setup TOTP": [
+        ""
+      ],
+      "Templates": [
+        ""
+      ],
+      "add new templates": [
+        ""
+      ],
+      "load more templates before the first one": [
+        ""
+      ],
+      "load newer templates": [
+        ""
+      ],
+      "delete selected templates from the database": [
+        ""
+      ],
+      "use template to create new order": [
+        ""
+      ],
+      "create qr code for the template": [
+        ""
+      ],
+      "load more templates after the last one": [
+        ""
+      ],
+      "load older templates": [
+        ""
+      ],
+      "There is no templates yet, add more pressing the + sign": [
+        ""
+      ],
+      "template delete successfully": [
+        ""
+      ],
+      "could not delete the template": [
+        ""
+      ],
+      "could not update template": [
+        ""
+      ],
+      "should be one of '%1$s'": [
+        ""
+      ],
+      "Webhook ID to use": [
+        ""
+      ],
+      "Event": [
+        ""
+      ],
+      "The event of the webhook: why the webhook is used": [
+        ""
+      ],
+      "Method": [
+        ""
+      ],
+      "Method used by the webhook": [
+        ""
+      ],
+      "URL": [
+        ""
+      ],
+      "URL of the webhook where the customer will be redirected": [
+        ""
+      ],
+      "Header": [
+        ""
+      ],
+      "Header template of the webhook": [
+        ""
+      ],
+      "Body": [
+        ""
+      ],
+      "Body template by the webhook": [
+        ""
+      ],
+      "Webhooks": [
+        ""
+      ],
+      "add new webhooks": [
+        ""
+      ],
+      "load more webhooks before the first one": [
+        ""
+      ],
+      "load newer webhooks": [
+        ""
+      ],
+      "Event type": [
+        ""
+      ],
+      "delete selected webhook from the database": [
+        ""
+      ],
+      "load more webhooks after the last one": [
+        ""
+      ],
+      "load older webhooks": [
+        ""
+      ],
+      "There is no webhooks yet, add more pressing the + sign": [
+        ""
+      ],
+      "webhook delete successfully": [
+        ""
+      ],
+      "could not delete the webhook": [
+        ""
+      ],
+      "check the id, does not look valid": [
+        ""
+      ],
+      "should have 52 characters, current %1$s": [
+        ""
+      ],
+      "URL doesn't have the right format": [
+        ""
+      ],
+      "Credited bank account": [
+        ""
+      ],
+      "Select one account": [
+        ""
+      ],
+      "Bank account of the merchant where the payment was received": [
+        ""
+      ],
+      "Wire transfer ID": [
+        ""
+      ],
+      "unique identifier of the wire transfer used by the exchange, must be 52 
characters long": [
+        ""
+      ],
+      "Base URL of the exchange that made the transfer, should have been in 
the wire transfer subject": [
+        ""
+      ],
+      "Amount credited": [
+        ""
+      ],
+      "Actual amount that was wired to the merchant's bank account": [
+        ""
+      ],
+      "could not inform transfer": [
+        ""
+      ],
+      "Transfers": [
+        ""
+      ],
+      "add new transfer": [
+        ""
+      ],
+      "load more transfers before the first one": [
+        ""
+      ],
+      "load newer transfers": [
+        ""
+      ],
+      "Credit": [
+        ""
+      ],
+      "Confirmed": [
+        ""
+      ],
+      "Verified": [
+        ""
+      ],
+      "Executed at": [
+        ""
+      ],
+      "yes": [
+        ""
+      ],
+      "no": [
+        ""
+      ],
+      "unknown": [
+        ""
+      ],
+      "delete selected transfer from the database": [
+        ""
+      ],
+      "load more transfer after the last one": [
+        ""
+      ],
+      "load older transfers": [
+        ""
+      ],
+      "There is no transfer yet, add more pressing the + sign": [
+        ""
+      ],
+      "filter by account address": [
+        ""
+      ],
+      "only show wire transfers confirmed by the merchant": [
+        ""
+      ],
+      "only show wire transfers claimed by the exchange": [
+        ""
+      ],
+      "Unverified": [
+        ""
+      ],
+      "is not valid": [
+        ""
+      ],
+      "is not a number": [
+        ""
+      ],
+      "must be 1 or greater": [
+        ""
+      ],
+      "max 7 lines": [
+        ""
+      ],
+      "change authorization configuration": [
+        ""
+      ],
+      "Need to complete marked fields and choose authorization method": [
+        ""
+      ],
+      "This is not a valid bitcoin address.": [
+        ""
+      ],
+      "This is not a valid Ethereum address.": [
+        ""
+      ],
+      "IBAN numbers usually have more that 4 digits": [
+        ""
+      ],
+      "IBAN numbers usually have less that 34 digits": [
+        ""
+      ],
+      "IBAN country code not found": [
+        ""
+      ],
+      "IBAN number is not valid, checksum is wrong": [
+        ""
+      ],
+      "Target type": [
+        ""
+      ],
+      "Method to use for wire transfer": [
+        ""
+      ],
+      "Routing": [
+        ""
+      ],
+      "Routing number.": [
+        ""
+      ],
+      "Account": [
+        ""
+      ],
+      "Account number.": [
+        ""
+      ],
+      "Business Identifier Code.": [
+        ""
+      ],
+      "Bank Account Number.": [
+        ""
+      ],
+      "Unified Payment Interface.": [
+        ""
+      ],
+      "Bitcoin protocol.": [
+        ""
+      ],
+      "Ethereum protocol.": [
+        ""
+      ],
+      "Interledger protocol.": [
+        ""
+      ],
+      "Host": [
+        ""
+      ],
+      "Bank host.": [
+        ""
+      ],
+      "Bank account.": [
+        ""
+      ],
+      "Bank account owner's name.": [
+        ""
+      ],
+      "No accounts yet.": [
+        ""
+      ],
+      "Name of the instance in URLs. The 'default' instance is special in that 
it is used to administer other instances.": [
+        ""
+      ],
+      "Business name": [
+        ""
+      ],
+      "Legal name of the business represented by this instance.": [
+        ""
+      ],
+      "Email": [
+        ""
+      ],
+      "Contact email": [
+        ""
+      ],
+      "Website URL": [
+        ""
+      ],
+      "URL.": [
+        ""
+      ],
+      "Logo": [
+        ""
+      ],
+      "Logo image.": [
+        ""
+      ],
+      "Bank account": [
+        ""
+      ],
+      "URI specifying bank account for crediting revenue.": [
+        ""
+      ],
+      "Default max deposit fee": [
+        ""
+      ],
+      "Maximum deposit fees this merchant is willing to pay per order by 
default.": [
+        ""
+      ],
+      "Default max wire fee": [
+        ""
+      ],
+      "Maximum wire fees this merchant is willing to pay per wire transfer by 
default.": [
+        ""
+      ],
+      "Default wire fee amortization": [
+        ""
+      ],
+      "Number of orders excess wire transfer fees will be divided by to 
compute per order surcharge.": [
+        ""
+      ],
+      "Physical location of the merchant.": [
+        ""
+      ],
+      "Jurisdiction": [
+        ""
+      ],
+      "Jurisdiction for legal disputes with the merchant.": [
+        ""
+      ],
+      "Default payment delay": [
+        ""
+      ],
+      "Time customers have to pay an order before the offer expires by 
default.": [
+        ""
+      ],
+      "Default wire transfer delay": [
+        ""
+      ],
+      "Maximum time an exchange is allowed to delay wiring funds to the 
merchant, enabling it to aggregate smaller payments into larger wire transfers 
and reducing wire fees.": [
+        ""
+      ],
+      "Instance id": [
+        ""
+      ],
+      "Change the authorization method use for this instance.": [
+        ""
+      ],
+      "Manage access token": [
+        ""
+      ],
+      "Failed to create instance": [
+        ""
+      ],
+      "Login required": [
+        ""
+      ],
+      "Please enter your access token.": [
+        ""
+      ],
+      "Access Token": [
+        ""
+      ],
+      "The request to the backend take too long and was cancelled": [
+        ""
+      ],
+      "Diagnostic from %1$s is \"%2$s\"": [
+        ""
+      ],
+      "The backend reported a problem: HTTP status #%1$s": [
+        ""
+      ],
+      "Diagnostic from %1$s is '%2$s'": [
+        ""
+      ],
+      "Access denied": [
+        ""
+      ],
+      "The access token provided is invalid.": [
+        ""
+      ],
+      "No 'default' instance configured yet.": [
+        ""
+      ],
+      "Create a 'default' instance to begin using the merchant backoffice.": [
+        ""
+      ],
+      "The access token provided is invalid": [
+        ""
+      ],
+      "Hide for today": [
+        ""
+      ],
+      "Instance": [
+        ""
+      ],
+      "Settings": [
+        ""
+      ],
+      "Connection": [
+        ""
+      ],
+      "New": [
+        ""
+      ],
+      "List": [
+        ""
+      ],
+      "Log out": [
+        ""
+      ],
+      "Check your token is valid": [
+        ""
+      ],
+      "Couldn't access the server.": [
+        ""
+      ],
+      "Could not infer instance id from url %1$s": [
+        ""
+      ],
+      "Server not found": [
+        ""
+      ],
+      "Server response with an error code": [
+        ""
+      ],
+      "Got message %1$s from %2$s": [
+        ""
+      ],
+      "Response from server is unreadable, http status: %1$s": [
+        ""
+      ],
+      "Unexpected Error": [
+        ""
+      ],
+      "The value %1$s is invalid for a payment url": [
+        ""
+      ],
+      "add element to the list": [
+        ""
+      ],
+      "add": [
+        ""
+      ],
+      "Deleting": [
+        ""
+      ],
+      "Changing": [
+        ""
+      ],
+      "Order ID": [
+        ""
+      ],
+      "Payment URL": [
+        ""
+      ]
+    }
+  }
+};
+
+strings['es'] = {
+  "domain": "messages",
+  "locale_data": {
+    "messages": {
+      "": {
+        "domain": "messages",
+        "plural_forms": "nplurals=2; plural=n != 1;",
+        "lang": "es"
+      },
+      "Cancel": [
+        "Cancelar"
+      ],
+      "%1$s": [
+        "%1$s"
+      ],
+      "Close": [
+        ""
+      ],
+      "Continue": [
+        "Continuar"
+      ],
+      "Clear": [
+        "Limpiar"
+      ],
+      "Confirm": [
+        "Confirmar"
+      ],
+      "is not the same as the current access token": [
+        "no es el mismo que el token de acceso actual"
+      ],
+      "cannot be empty": [
+        "no puede ser vacío"
+      ],
+      "cannot be the same as the old token": [
+        "no puede ser igual al viejo token"
+      ],
+      "is not the same": [
+        "no son iguales"
+      ],
+      "You are updating the access token from instance with id %1$s": [
+        "Está actualizando el token de acceso para la instancia con id %1$s"
+      ],
+      "Old access token": [
+        "Viejo token de acceso"
+      ],
+      "access token currently in use": [
+        "acceder al token en uso actualmente"
+      ],
+      "New access token": [
+        "Nuevo token de acceso"
+      ],
+      "next access token to be used": [
+        "siguiente token de acceso a usar"
+      ],
+      "Repeat access token": [
+        "Repetir token de acceso"
+      ],
+      "confirm the same access token": [
+        "confirmar el mismo token de acceso"
+      ],
+      "Clearing the access token will mean public access to the instance": [
+        "Limpiar el token de acceso significa acceso público a la instancia"
+      ],
+      "cannot be the same as the old access token": [
+        "no puede ser igual al anterior token de acceso"
+      ],
+      "You are setting the access token for the new instance": [
+        "Está estableciendo el token de acceso para la nueva instancia"
+      ],
+      "With external authorization method no check will be done by the 
merchant backend": [
+        "Con el método de autorización externa no se hará ninguna revisión por 
el backend del comerciante"
+      ],
+      "Set external authorization": [
+        "Establecer autorización externa"
+      ],
+      "Set access token": [
+        "Establecer token de acceso"
+      ],
+      "Operation in progress...": [
+        "Operación en progreso..."
+      ],
+      "The operation will be automatically canceled after %1$s seconds": [
+        "La operación será automáticamente cancelada luego de %1$s segundos"
+      ],
+      "Instances": [
+        "Instancias"
+      ],
+      "Delete": [
+        "Eliminar"
+      ],
+      "add new instance": [
+        "agregar nueva instancia"
+      ],
+      "ID": [
+        "ID"
+      ],
+      "Name": [
+        "Nombre"
+      ],
+      "Edit": [
+        "Editar"
+      ],
+      "Purge": [
+        "Purgar"
+      ],
+      "There is no instances yet, add more pressing the + sign": [
+        "Todavía no hay instancias, agregue más presionando el signo +"
+      ],
+      "Only show active instances": [
+        "Solo mostrar instancias activas"
+      ],
+      "Active": [
+        "Activo"
+      ],
+      "Only show deleted instances": [
+        "Mostrar solo instancias eliminadas"
+      ],
+      "Deleted": [
+        "Eliminado"
+      ],
+      "Show all instances": [
+        "Mostrar todas las instancias"
+      ],
+      "All": [
+        "Todo"
+      ],
+      "Instance \"%1$s\" (ID: %2$s) has been deleted": [
+        "La instancia '%1$s' (ID: %2$s) fue eliminada"
+      ],
+      "Failed to delete instance": [
+        "Fallo al eliminar instancia"
+      ],
+      "Instance '%1$s' (ID: %2$s) has been disabled": [
+        "Instance '%1$s' (ID: %2$s) ha sido deshabilitada"
+      ],
+      "Failed to purge instance": [
+        "Fallo al purgar la instancia"
+      ],
+      "Pending KYC verification": [
+        "Verificación KYC pendiente"
+      ],
+      "Timed out": [
+        "Expirado"
+      ],
+      "Exchange": [
+        "Exchange"
+      ],
+      "Target account": [
+        "Cuenta objetivo"
+      ],
+      "KYC URL": [
+        "URL de KYC"
+      ],
+      "Code": [
+        "Código"
+      ],
+      "Http Status": [
+        "Estado http"
+      ],
+      "No pending kyc verification!": [
+        "¡No hay verificación kyc pendiente!"
+      ],
+      "change value to unknown date": [
+        "cambiar valor a fecha desconocida"
+      ],
+      "change value to empty": [
+        "cambiar valor a vacío"
+      ],
+      "clear": [
+        "limpiar"
+      ],
+      "change value to never": [
+        "cambiar valor a nunca"
+      ],
+      "never": [
+        "nunca"
+      ],
+      "Country": [
+        "País"
+      ],
+      "Address": [
+        "Dirección"
+      ],
+      "Building number": [
+        "Número de edificio"
+      ],
+      "Building name": [
+        "Nombre de edificio"
+      ],
+      "Street": [
+        "Calle"
+      ],
+      "Post code": [
+        "Código postal"
+      ],
+      "Town location": [
+        "Ubicación de ciudad"
+      ],
+      "Town": [
+        "Ciudad"
+      ],
+      "District": [
+        "Distrito"
+      ],
+      "Country subdivision": [
+        "Subdivisión de país"
+      ],
+      "Product id": [
+        "Id de producto"
+      ],
+      "Description": [
+        "Descripcion"
+      ],
+      "Product": [
+        "Productos"
+      ],
+      "search products by it's description or id": [
+        "buscar productos por su descripción o ID"
+      ],
+      "no products found with that description": [
+        "no se encontraron productos con esa descripción"
+      ],
+      "You must enter a valid product identifier.": [
+        "Debe ingresar un identificador de producto válido."
+      ],
+      "Quantity must be greater than 0!": [
+        "¡Cantidad debe ser mayor que 0!"
+      ],
+      "This quantity exceeds remaining stock. Currently, only %1$s units 
remain unreserved in stock.": [
+        "Esta cantidad excede las existencias restantes. Actualmente, solo 
quedan %1$s unidades sin reservar en las existencias."
+      ],
+      "Quantity": [
+        "Cantidad"
+      ],
+      "how many products will be added": [
+        "cuántos productos serán agregados"
+      ],
+      "Add from inventory": [
+        "Agregar del inventario"
+      ],
+      "Image should be smaller than 1 MB": [
+        "La imagen debe ser mas chica que 1 MB"
+      ],
+      "Add": [
+        "Agregar"
+      ],
+      "Remove": [
+        "Eliminar"
+      ],
+      "No taxes configured for this product.": [
+        "Ningun impuesto configurado para este producto."
+      ],
+      "Amount": [
+        "Monto"
+      ],
+      "Taxes can be in currencies that differ from the main currency used by 
the merchant.": [
+        "Impuestos pueden estar en divisas que difieren de la principal divisa 
usada por el comerciante."
+      ],
+      "Enter currency and value separated with a colon, e.g. 
&quot;USD:2.3&quot;.": [
+        "Ingrese divisa y valor separado por dos puntos, e.g. 
&quot;USD:2.3&quot;."
+      ],
+      "Legal name of the tax, e.g. VAT or import duties.": [
+        "Nombre legal del impuesto, e.g. IVA o arancel."
+      ],
+      "add tax to the tax list": [
+        "agregar impuesto a la lista de impuestos"
+      ],
+      "describe and add a product that is not in the inventory list": [
+        "describa y agregue un producto que no está en la lista de inventarios"
+      ],
+      "Add custom product": [
+        "Agregue un producto personalizado"
+      ],
+      "Complete information of the product": [
+        "Complete información del producto"
+      ],
+      "Image": [
+        "Imagen"
+      ],
+      "photo of the product": [
+        "foto del producto"
+      ],
+      "full product description": [
+        "descripción completa del producto"
+      ],
+      "Unit": [
+        "Unidad"
+      ],
+      "name of the product unit": [
+        "nombre de la unidad del producto"
+      ],
+      "Price": [
+        "Precio"
+      ],
+      "amount in the current currency": [
+        "monto de la divisa actual"
+      ],
+      "Taxes": [
+        "Impuestos"
+      ],
+      "image": [
+        "imagen"
+      ],
+      "description": [
+        "descripción"
+      ],
+      "quantity": [
+        "cantidad"
+      ],
+      "unit price": [
+        "precio unitario"
+      ],
+      "total price": [
+        "precio total"
+      ],
+      "required": [
+        "requerido"
+      ],
+      "not valid": [
+        "no es un json válido"
+      ],
+      "must be greater than 0": [
+        "debe ser mayor que 0"
+      ],
+      "not a valid json": [
+        "no es un json válido"
+      ],
+      "should be in the future": [
+        "deberían ser en el futuro"
+      ],
+      "refund deadline cannot be before pay deadline": [
+        "plazo de reembolso no puede ser antes que el plazo de pago"
+      ],
+      "wire transfer deadline cannot be before refund deadline": [
+        "el plazo de la transferencia bancaria no puede ser antes que el plazo 
de reembolso"
+      ],
+      "wire transfer deadline cannot be before pay deadline": [
+        "el plazo de la transferencia bancaria no puede ser antes que el plazo 
de pago"
+      ],
+      "should have a refund deadline": [
+        "debería tener un plazo de reembolso"
+      ],
+      "auto refund cannot be after refund deadline": [
+        "reembolso automático no puede ser después qu el plazo de reembolso"
+      ],
+      "Manage products in order": [
+        "Manejar productos en orden"
+      ],
+      "Manage list of products in the order.": [
+        "Manejar lista de productos en la orden."
+      ],
+      "Remove this product from the order.": [
+        "Remover este producto de la orden."
+      ],
+      "Total price": [
+        "Precio total"
+      ],
+      "total product price added up": [
+        "precio total de producto agregado"
+      ],
+      "Amount to be paid by the customer": [
+        "Monto a ser pagado por el cliente"
+      ],
+      "Order price": [
+        "Precio de la orden"
+      ],
+      "final order price": [
+        "Precio final de la orden"
+      ],
+      "Summary": [
+        "Resumen"
+      ],
+      "Title of the order to be shown to the customer": [
+        "Título de la orden a ser mostrado al cliente"
+      ],
+      "Shipping and Fulfillment": [
+        "Envío y cumplimiento"
+      ],
+      "Delivery date": [
+        "Fecha de entrega"
+      ],
+      "Deadline for physical delivery assured by the merchant.": [
+        "Plazo para la entrega física asegurado por el comerciante."
+      ],
+      "Location": [
+        "Ubicación"
+      ],
+      "address where the products will be delivered": [
+        "dirección a donde los productos serán entregados"
+      ],
+      "Fulfillment URL": [
+        "URL de cumplimiento"
+      ],
+      "URL to which the user will be redirected after successful payment.": [
+        "URL al cual el usuario será redirigido luego de pago exitoso."
+      ],
+      "Taler payment options": [
+        "Opciones de pago de Taler"
+      ],
+      "Override default Taler payment settings for this order": [
+        "Sobreescribir pagos por omisión de Taler para esta orden"
+      ],
+      "Payment deadline": [
+        "Plazo de pago"
+      ],
+      "Deadline for the customer to pay for the offer before it expires. 
Inventory products will be reserved until this deadline.": [
+        "Plazo límite para que el cliente pague por la oferta antes de que 
expire. Productos del inventario serán reservados hasta este plazo límite."
+      ],
+      "Refund deadline": [
+        "Plazo de reembolso"
+      ],
+      "Time until which the order can be refunded by the merchant.": [
+        "Tiempo hasta el cual la orden puede ser reembolsada por el 
comerciante."
+      ],
+      "Wire transfer deadline": [
+        "Plazo de la transferencia"
+      ],
+      "Deadline for the exchange to make the wire transfer.": [
+        "Plazo para que el exchange haga la transferencia."
+      ],
+      "Auto-refund deadline": [
+        "Plazo de reembolso automático"
+      ],
+      "Time until which the wallet will automatically check for refunds 
without user interaction.": [
+        "Tiempo hasta el cual la billetera será automáticamente revisada por 
reembolsos win interación por parte del usuario."
+      ],
+      "Maximum deposit fee": [
+        "Máxima tarifa de depósito"
+      ],
+      "Maximum deposit fees the merchant is willing to cover for this order. 
Higher deposit fees must be covered in full by the consumer.": [
+        "Máxima tarifa de depósito que el comerciante esta dispuesto a cubir 
para esta orden. Mayores tarifas de depósito deben ser cubiertas completamente 
por el consumidor."
+      ],
+      "Maximum wire fee": [
+        "Máxima tarifa de transferencia"
+      ],
+      "Maximum aggregate wire fees the merchant is willing to cover for this 
order. Wire fees exceeding this amount are to be covered by the customers.": [
+        ""
+      ],
+      "Wire fee amortization": [
+        "Amortización de comisión de transferencia"
+      ],
+      "Factor by which wire fees exceeding the above threshold are divided to 
determine the share of excess wire fees to be paid explicitly by the 
consumer.": [
+        ""
+      ],
+      "Create token": [
+        "Administrar token"
+      ],
+      "Uncheck this option if the merchant backend generated an order ID with 
enough entropy to prevent adversarial claims.": [
+        ""
+      ],
+      "Minimum age required": [
+        "Login necesario"
+      ],
+      "Any value greater than 0 will limit the coins able be used to pay this 
contract. If empty the age restriction will be defined by the products": [
+        ""
+      ],
+      "Min age defined by the producs is %1$s": [
+        ""
+      ],
+      "Additional information": [
+        "Información extra"
+      ],
+      "Custom information to be included in the contract for this order.": [
+        ""
+      ],
+      "You must enter a value in JavaScript Object Notation (JSON).": [
+        ""
+      ],
+      "days": [
+        "días"
+      ],
+      "hours": [
+        "horas"
+      ],
+      "minutes": [
+        "minutos"
+      ],
+      "seconds": [
+        "segundos"
+      ],
+      "forever": [
+        "nunca"
+      ],
+      "%1$sM": [
+        ""
+      ],
+      "%1$sY": [
+        ""
+      ],
+      "%1$sd": [
+        ""
+      ],
+      "%1$sh": [
+        ""
+      ],
+      "%1$smin": [
+        ""
+      ],
+      "%1$ssec": [
+        ""
+      ],
+      "Orders": [
+        "Órdenes"
+      ],
+      "create order": [
+        "creado"
+      ],
+      "load newer orders": [
+        "cargar nuevas ordenes"
+      ],
+      "Date": [
+        "Fecha"
+      ],
+      "Refund": [
+        "Devolución"
+      ],
+      "copy url": [
+        "copiar url"
+      ],
+      "load older orders": [
+        "cargar viejas ordenes"
+      ],
+      "No orders have been found matching your query!": [
+        "¡No se encontraron órdenes que emparejen su búsqueda!"
+      ],
+      "duplicated": [
+        "duplicado"
+      ],
+      "invalid format": [
+        "formato inválido"
+      ],
+      "this value exceed the refundable amount": [
+        "este monto excede el monto reembolsable"
+      ],
+      "date": [
+        "fecha"
+      ],
+      "amount": [
+        "monto"
+      ],
+      "reason": [
+        "razón"
+      ],
+      "amount to be refunded": [
+        "monto a ser reembolsado"
+      ],
+      "Max refundable:": [
+        "Máximo reembolzable:"
+      ],
+      "Reason": [
+        "Razón"
+      ],
+      "Choose one...": [
+        "Elija uno..."
+      ],
+      "requested by the customer": [
+        "pedido por el consumidor"
+      ],
+      "other": [
+        "otro"
+      ],
+      "why this order is being refunded": [
+        "por qué esta orden está siendo reembolsada"
+      ],
+      "more information to give context": [
+        "más información para dar contexto"
+      ],
+      "Contract Terms": [
+        "Términos de contrato"
+      ],
+      "human-readable description of the whole purchase": [
+        "descripción legible de toda la compra"
+      ],
+      "total price for the transaction": [
+        "precio total de la transacción"
+      ],
+      "URL for this purchase": [
+        "URL para esta compra"
+      ],
+      "Max fee": [
+        "Máxima comisión"
+      ],
+      "maximum total deposit fee accepted by the merchant for this contract": [
+        ""
+      ],
+      "Max wire fee": [
+        "Impuesto de transferencia máximo"
+      ],
+      "maximum wire fee accepted by the merchant": [
+        ""
+      ],
+      "over how many customer transactions does the merchant expect to 
amortize wire fees on average": [
+        ""
+      ],
+      "Created at": [
+        "Creado en"
+      ],
+      "time when this contract was generated": [
+        ""
+      ],
+      "after this deadline has passed no refunds will be accepted": [
+        ""
+      ],
+      "after this deadline, the merchant won't accept payments for the 
contract": [
+        ""
+      ],
+      "transfer deadline for the exchange": [
+        ""
+      ],
+      "time indicating when the order should be delivered": [
+        ""
+      ],
+      "where the order will be delivered": [
+        ""
+      ],
+      "Auto-refund delay": [
+        "Plazo de reembolso automático"
+      ],
+      "how long the wallet should try to get an automatic refund for the 
purchase": [
+        ""
+      ],
+      "Extra info": [
+        "Información extra"
+      ],
+      "extra data that is only interpreted by the merchant frontend": [
+        ""
+      ],
+      "Order": [
+        "Orden"
+      ],
+      "claimed": [
+        "reclamado"
+      ],
+      "claimed at": [
+        "reclamado"
+      ],
+      "Timeline": [
+        "Cronología"
+      ],
+      "Payment details": [
+        "Detalles de pago"
+      ],
+      "Order status": [
+        "Estado de orden"
+      ],
+      "Product list": [
+        "Lista de producto"
+      ],
+      "paid": [
+        "pagados"
+      ],
+      "wired": [
+        "transferido"
+      ],
+      "refunded": [
+        "reembolzado"
+      ],
+      "refund order": [
+        "reembolzado"
+      ],
+      "not refundable": [
+        "Máximo reembolzable:"
+      ],
+      "refund": [
+        "reembolzar"
+      ],
+      "Refunded amount": [
+        "Monto reembolzado"
+      ],
+      "Refund taken": [
+        "Reembolzado"
+      ],
+      "Status URL": [
+        "URL de estado de orden"
+      ],
+      "Refund URI": [
+        "Devolución"
+      ],
+      "unpaid": [
+        "impago"
+      ],
+      "pay at": [
+        "pagar en"
+      ],
+      "created at": [
+        "creado"
+      ],
+      "Order status URL": [
+        "URL de estado de orden"
+      ],
+      "Payment URI": [
+        "URI de pago"
+      ],
+      "Unknown order status. This is an error, please contact the 
administrator.": [
+        "Estado de orden desconocido. Esto es un error, por favor contacte a 
su administrador."
+      ],
+      "Back": [
+        ""
+      ],
+      "refund created successfully": [
+        "reembolzo creado satisfactoriamente"
+      ],
+      "could not create the refund": [
+        "No se pudo create el reembolso"
+      ],
+      "select date to show nearby orders": [
+        ""
+      ],
+      "order id": [
+        "ir a id de orden"
+      ],
+      "jump to order with the given order ID": [
+        ""
+      ],
+      "remove all filters": [
+        ""
+      ],
+      "only show paid orders": [
+        ""
+      ],
+      "Paid": [
+        "Pagado"
+      ],
+      "only show orders with refunds": [
+        "No se pudo create el reembolso"
+      ],
+      "Refunded": [
+        "Reembolzado"
+      ],
+      "only show orders where customers paid, but wire payments from payment 
provider are still pending": [
+        ""
+      ],
+      "Not wired": [
+        "No transferido"
+      ],
+      "clear date filter": [
+        ""
+      ],
+      "date (YYYY/MM/DD)": [
+        ""
+      ],
+      "Enter an order id": [
+        "ir a id de orden"
+      ],
+      "order not found": [
+        "Servidor no encontrado"
+      ],
+      "could not get the order to refund": [
+        "No se pudo create el reembolso"
+      ],
+      "Loading...": [
+        "Cargando..."
+      ],
+      "click here to configure the stock of the product, leave it as is and 
the backend will not control stock": [
+        ""
+      ],
+      "Manage stock": [
+        "Administrar stock"
+      ],
+      "this product has been configured without stock control": [
+        ""
+      ],
+      "Infinite": [
+        "Inifinito"
+      ],
+      "lost cannot be greater than current and incoming (max %1$s)": [
+        "la pérdida no puede ser mayor al stock actual + entrante (max %1$s )"
+      ],
+      "Incoming": [
+        "Ingresando"
+      ],
+      "Lost": [
+        "Perdido"
+      ],
+      "Current": [
+        "Actual"
+      ],
+      "remove stock control for this product": [
+        ""
+      ],
+      "without stock": [
+        "sin stock"
+      ],
+      "Next restock": [
+        "Próximo reabastecimiento"
+      ],
+      "Delivery address": [
+        "Dirección de entrega"
+      ],
+      "product identification to use in URLs (for internal use only)": [
+        ""
+      ],
+      "illustration of the product for customers": [
+        ""
+      ],
+      "product description for customers": [
+        ""
+      ],
+      "Age restricted": [
+        ""
+      ],
+      "is this product restricted for customer below certain age?": [
+        ""
+      ],
+      "unit describing quantity of product sold (e.g. 2 kilograms, 5 liters, 3 
items, 5 meters) for customers": [
+        ""
+      ],
+      "sale price for customers, including taxes, for above units of the 
product": [
+        ""
+      ],
+      "Stock": [
+        "Existencias"
+      ],
+      "product inventory for products with finite supply (for internal use 
only)": [
+        ""
+      ],
+      "taxes included in the product price, exposed to customers": [
+        ""
+      ],
+      "Need to complete marked fields": [
+        ""
+      ],
+      "could not create product": [
+        "no se pudo crear el producto"
+      ],
+      "Products": [
+        "Productos"
+      ],
+      "add product to inventory": [
+        ""
+      ],
+      "Sell": [
+        "Venta"
+      ],
+      "Profit": [
+        "Ganancia"
+      ],
+      "Sold": [
+        "Vendido"
+      ],
+      "free": [
+        "Gratis"
+      ],
+      "go to product update page": [
+        "producto actualizado correctamente"
+      ],
+      "Update": [
+        "Actualizar"
+      ],
+      "remove this product from the database": [
+        ""
+      ],
+      "update the product with new price": [
+        ""
+      ],
+      "update product with new price": [
+        ""
+      ],
+      "add more elements to the inventory": [
+        ""
+      ],
+      "report elements lost in the inventory": [
+        ""
+      ],
+      "new price for the product": [
+        "no se pudo actualizar el producto"
+      ],
+      "the are value with errors": [
+        ""
+      ],
+      "update product with new stock and price": [
+        ""
+      ],
+      "There is no products yet, add more pressing the + sign": [
+        "No hay propinas todavía, agregar mas presionando el signo +"
+      ],
+      "product updated successfully": [
+        "producto actualizado correctamente"
+      ],
+      "could not update the product": [
+        "no se pudo actualizar el producto"
+      ],
+      "product delete successfully": [
+        "producto fue eliminado correctamente"
+      ],
+      "could not delete the product": [
+        "no se pudo eliminar el producto"
+      ],
+      "Product id:": [
+        "Id de producto"
+      ],
+      "To complete the setup of the reserve, you must now initiate a wire 
transfer using the given wire transfer subject and crediting the specified 
amount to the indicated account of the exchange.": [
+        ""
+      ],
+      "If your system supports RFC 8905, you can do this by opening this 
URI:": [
+        ""
+      ],
+      "it should be greater than 0": [
+        "Debe ser mayor a 0"
+      ],
+      "must be a valid URL": [
+        ""
+      ],
+      "Initial balance": [
+        "Instancia"
+      ],
+      "balance prior to deposit": [
+        ""
+      ],
+      "Exchange URL": [
+        "URL del Exchange"
+      ],
+      "URL of exchange": [
+        ""
+      ],
+      "Next": [
+        "Siguiente"
+      ],
+      "Wire method": [
+        ""
+      ],
+      "method to use for wire transfer": [
+        "no se pudo informar la transferencia"
+      ],
+      "Select one wire method": [
+        ""
+      ],
+      "could not create reserve": [
+        "No se pudo create el reembolso"
+      ],
+      "Valid until": [
+        "Válido hasta"
+      ],
+      "Created balance": [
+        "creado"
+      ],
+      "Exchange balance": [
+        "Monto inicial"
+      ],
+      "Picked up": [
+        ""
+      ],
+      "Committed": [
+        "Monto confirmado"
+      ],
+      "Account address": [
+        "Dirección de cuenta"
+      ],
+      "Subject": [
+        "Asunto"
+      ],
+      "Tips": [
+        "Propinas"
+      ],
+      "No tips has been authorized from this reserve": [
+        ""
+      ],
+      "Authorized": [
+        "Token de autorización"
+      ],
+      "Expiration": [
+        "Información extra"
+      ],
+      "amount of tip": [
+        "monto"
+      ],
+      "Justification": [
+        "Jurisdicción"
+      ],
+      "reason for the tip": [
+        ""
+      ],
+      "URL after tip": [
+        ""
+      ],
+      "URL to visit after tip payment": [
+        ""
+      ],
+      "Reserves not yet funded": [
+        "Servidor no encontrado"
+      ],
+      "Reserves ready": [
+        ""
+      ],
+      "add new reserve": [
+        "cargar nuevas transferencias"
+      ],
+      "Expires at": [
+        ""
+      ],
+      "Initial": [
+        ""
+      ],
+      "delete selected reserve from the database": [
+        ""
+      ],
+      "authorize new tip from selected reserve": [
+        ""
+      ],
+      "There is no ready reserves yet, add more pressing the + sign or fund 
them": [
+        "No hay transferencias todavía, agregar mas presionando el signo +"
+      ],
+      "Expected Balance": [
+        "Ejecutado en"
+      ],
+      "could not create the tip": [
+        "No se pudo create el reembolso"
+      ],
+      "should not be empty": [
+        "no puede ser vacío"
+      ],
+      "should be greater that 0": [
+        "Debe ser mayor a 0"
+      ],
+      "can't be empty": [
+        "no puede ser vacío"
+      ],
+      "to short": [
+        ""
+      ],
+      "just letters and numbers from 2 to 7": [
+        ""
+      ],
+      "size of the key should be 32": [
+        ""
+      ],
+      "Identifier": [
+        ""
+      ],
+      "Name of the template in URLs.": [
+        ""
+      ],
+      "Describe what this template stands for": [
+        ""
+      ],
+      "Fixed summary": [
+        "Estado de orden"
+      ],
+      "If specified, this template will create order with the same summary": [
+        ""
+      ],
+      "Fixed price": [
+        "precio unitario"
+      ],
+      "If specified, this template will create order with the same price": [
+        ""
+      ],
+      "Minimum age": [
+        "Edad mínima"
+      ],
+      "Is this contract restricted to some age?": [
+        ""
+      ],
+      "Payment timeout": [
+        "Opciones de pago"
+      ],
+      "How much time has the customer to complete the payment once the order 
was created.": [
+        ""
+      ],
+      "Verification algorithm": [
+        ""
+      ],
+      "Algorithm to use to verify transaction in offline mode": [
+        ""
+      ],
+      "Point-of-sale key": [
+        ""
+      ],
+      "Useful to validate the purchase": [
+        ""
+      ],
+      "generate random secret key": [
+        ""
+      ],
+      "random": [
+        ""
+      ],
+      "show secret key": [
+        ""
+      ],
+      "hide secret key": [
+        ""
+      ],
+      "hide": [
+        ""
+      ],
+      "show": [
+        ""
+      ],
+      "could not inform template": [
+        "no se pudo informar la transferencia"
+      ],
+      "Amount is required": [
+        "Login necesario"
+      ],
+      "Order summary is required": [
+        ""
+      ],
+      "New order for template": [
+        "cargar viejas transferencias"
+      ],
+      "Amount of the order": [
+        ""
+      ],
+      "Order summary": [
+        "Estado de orden"
+      ],
+      "could not create order from template": [
+        "No se pudo create el reembolso"
+      ],
+      "Here you can specify a default value for fields that are not fixed. 
Default values can be edited by the customer before the payment.": [
+        ""
+      ],
+      "Fixed amount": [
+        "Monto reembolzado"
+      ],
+      "Default amount": [
+        "Monto reembolzado"
+      ],
+      "Default summary": [
+        "Estado de orden"
+      ],
+      "Print": [
+        ""
+      ],
+      "Setup TOTP": [
+        ""
+      ],
+      "Templates": [
+        ""
+      ],
+      "add new templates": [
+        ""
+      ],
+      "load more templates before the first one": [
+        ""
+      ],
+      "load newer templates": [
+        "cargar nuevas transferencias"
+      ],
+      "delete selected templates from the database": [
+        ""
+      ],
+      "use template to create new order": [
+        ""
+      ],
+      "create qr code for the template": [
+        "No se pudo create el reembolso"
+      ],
+      "load more templates after the last one": [
+        ""
+      ],
+      "load older templates": [
+        "cargar viejas transferencias"
+      ],
+      "There is no templates yet, add more pressing the + sign": [
+        "No hay propinas todavía, agregar mas presionando el signo +"
+      ],
+      "template delete successfully": [
+        "producto fue eliminado correctamente"
+      ],
+      "could not delete the template": [
+        "no se pudo eliminar el producto"
+      ],
+      "could not update template": [
+        "no se pudo actualizar el producto"
+      ],
+      "should be one of '%1$s'": [
+        "deberían ser iguales"
+      ],
+      "Webhook ID to use": [
+        ""
+      ],
+      "Event": [
+        ""
+      ],
+      "The event of the webhook: why the webhook is used": [
+        ""
+      ],
+      "Method": [
+        ""
+      ],
+      "Method used by the webhook": [
+        ""
+      ],
+      "URL": [
+        "URL"
+      ],
+      "URL of the webhook where the customer will be redirected": [
+        ""
+      ],
+      "Header": [
+        ""
+      ],
+      "Header template of the webhook": [
+        ""
+      ],
+      "Body": [
+        ""
+      ],
+      "Body template by the webhook": [
+        ""
+      ],
+      "Webhooks": [
+        ""
+      ],
+      "add new webhooks": [
+        ""
+      ],
+      "load more webhooks before the first one": [
+        ""
+      ],
+      "load newer webhooks": [
+        "cargar nuevas ordenes"
+      ],
+      "Event type": [
+        ""
+      ],
+      "delete selected webhook from the database": [
+        ""
+      ],
+      "load more webhooks after the last one": [
+        ""
+      ],
+      "load older webhooks": [
+        "cargar viejas ordenes"
+      ],
+      "There is no webhooks yet, add more pressing the + sign": [
+        "No hay propinas todavía, agregar mas presionando el signo +"
+      ],
+      "webhook delete successfully": [
+        "producto fue eliminado correctamente"
+      ],
+      "could not delete the webhook": [
+        "no se pudo eliminar el producto"
+      ],
+      "check the id, does not look valid": [
+        "verificar el id, no parece válido"
+      ],
+      "should have 52 characters, current %1$s": [
+        "debería tener 52 caracteres, actualmente %1$s"
+      ],
+      "URL doesn't have the right format": [
+        "La URL no tiene el formato correcto"
+      ],
+      "Credited bank account": [
+        ""
+      ],
+      "Select one account": [
+        ""
+      ],
+      "Bank account of the merchant where the payment was received": [
+        ""
+      ],
+      "Wire transfer ID": [
+        "Id de transferencia"
+      ],
+      "unique identifier of the wire transfer used by the exchange, must be 52 
characters long": [
+        ""
+      ],
+      "Base URL of the exchange that made the transfer, should have been in 
the wire transfer subject": [
+        ""
+      ],
+      "Amount credited": [
+        ""
+      ],
+      "Actual amount that was wired to the merchant's bank account": [
+        ""
+      ],
+      "could not inform transfer": [
+        "no se pudo informar la transferencia"
+      ],
+      "Transfers": [
+        "Transferencias"
+      ],
+      "add new transfer": [
+        "cargar nuevas transferencias"
+      ],
+      "load more transfers before the first one": [
+        ""
+      ],
+      "load newer transfers": [
+        "cargar nuevas transferencias"
+      ],
+      "Credit": [
+        "Crédito"
+      ],
+      "Confirmed": [
+        "Confirmado"
+      ],
+      "Verified": [
+        "Verificado"
+      ],
+      "Executed at": [
+        "Ejecutado en"
+      ],
+      "yes": [
+        "si"
+      ],
+      "no": [
+        "no"
+      ],
+      "unknown": [
+        "desconocido"
+      ],
+      "delete selected transfer from the database": [
+        "eliminar transferencia seleccionada de la base de datos"
+      ],
+      "load more transfer after the last one": [
+        "cargue más transferencia luego de la última"
+      ],
+      "load older transfers": [
+        "cargar viejas transferencias"
+      ],
+      "There is no transfer yet, add more pressing the + sign": [
+        "No hay transferencias todavía, agregar mas presionando el signo +"
+      ],
+      "filter by account address": [
+        "Dirección de cuenta"
+      ],
+      "only show wire transfers confirmed by the merchant": [
+        ""
+      ],
+      "only show wire transfers claimed by the exchange": [
+        ""
+      ],
+      "Unverified": [
+        "Verificado"
+      ],
+      "is not valid": [
+        ""
+      ],
+      "is not a number": [
+        "Número de edificio"
+      ],
+      "must be 1 or greater": [
+        "debe ser 1 o mayor"
+      ],
+      "max 7 lines": [
+        "máximo 7 líneas"
+      ],
+      "change authorization configuration": [
+        "cambiar configuración de autorización"
+      ],
+      "Need to complete marked fields and choose authorization method": [
+        "Necesita completar campos marcados y escoger un método de 
autorización"
+      ],
+      "This is not a valid bitcoin address.": [
+        "Esta no es una dirección de bitcoin válida."
+      ],
+      "This is not a valid Ethereum address.": [
+        "Esta no es una dirección de Ethereum válida."
+      ],
+      "IBAN numbers usually have more that 4 digits": [
+        "Números IBAN usualmente tienen más de 4 dígitos"
+      ],
+      "IBAN numbers usually have less that 34 digits": [
+        "Número IBAN usualmente tienen menos de 34 dígitos"
+      ],
+      "IBAN country code not found": [
+        "Código IBAN de país no encontrado"
+      ],
+      "IBAN number is not valid, checksum is wrong": [
+        "Número IBAN no es válido, la suma de verificación es incorrecta"
+      ],
+      "Target type": [
+        "Tipo objetivo"
+      ],
+      "Method to use for wire transfer": [
+        "Método a usar para la transferencia"
+      ],
+      "Routing": [
+        "Enrutamiento"
+      ],
+      "Routing number.": [
+        "Número de enrutamiento."
+      ],
+      "Account": [
+        "Cuenta"
+      ],
+      "Account number.": [
+        "Dirección de cuenta"
+      ],
+      "Business Identifier Code.": [
+        ""
+      ],
+      "Bank Account Number.": [
+        ""
+      ],
+      "Unified Payment Interface.": [
+        "Interfaz de pago unificado."
+      ],
+      "Bitcoin protocol.": [
+        ""
+      ],
+      "Ethereum protocol.": [
+        ""
+      ],
+      "Interledger protocol.": [
+        ""
+      ],
+      "Host": [
+        ""
+      ],
+      "Bank host.": [
+        ""
+      ],
+      "Bank account.": [
+        ""
+      ],
+      "Bank account owner's name.": [
+        ""
+      ],
+      "No accounts yet.": [
+        ""
+      ],
+      "Name of the instance in URLs. The 'default' instance is special in that 
it is used to administer other instances.": [
+        ""
+      ],
+      "Business name": [
+        "Nombre de edificio"
+      ],
+      "Legal name of the business represented by this instance.": [
+        ""
+      ],
+      "Email": [
+        ""
+      ],
+      "Contact email": [
+        ""
+      ],
+      "Website URL": [
+        "URL de sitio web"
+      ],
+      "URL.": [
+        ""
+      ],
+      "Logo": [
+        ""
+      ],
+      "Logo image.": [
+        ""
+      ],
+      "Bank account": [
+        "Cuenta bancaria"
+      ],
+      "URI specifying bank account for crediting revenue.": [
+        ""
+      ],
+      "Default max deposit fee": [
+        "Impuesto máximo de deposito por omisión"
+      ],
+      "Maximum deposit fees this merchant is willing to pay per order by 
default.": [
+        ""
+      ],
+      "Default max wire fee": [
+        "Impuesto máximo de transferencia por omisión"
+      ],
+      "Maximum wire fees this merchant is willing to pay per wire transfer by 
default.": [
+        ""
+      ],
+      "Default wire fee amortization": [
+        "Amortización de impuesto de transferencia por omisión"
+      ],
+      "Number of orders excess wire transfer fees will be divided by to 
compute per order surcharge.": [
+        ""
+      ],
+      "Physical location of the merchant.": [
+        ""
+      ],
+      "Jurisdiction": [
+        "Jurisdicción"
+      ],
+      "Jurisdiction for legal disputes with the merchant.": [
+        "Jurisdicción para disputas legales con el comerciante."
+      ],
+      "Default payment delay": [
+        "Retrazo de pago por omisión"
+      ],
+      "Time customers have to pay an order before the offer expires by 
default.": [
+        ""
+      ],
+      "Default wire transfer delay": [
+        "Retrazo de transferencia por omisión"
+      ],
+      "Maximum time an exchange is allowed to delay wiring funds to the 
merchant, enabling it to aggregate smaller payments into larger wire transfers 
and reducing wire fees.": [
+        ""
+      ],
+      "Instance id": [
+        "ID de instancia"
+      ],
+      "Change the authorization method use for this instance.": [
+        "Limpiar el token de autorización significa acceso público a la 
instancia"
+      ],
+      "Manage access token": [
+        "Administrar token de acceso"
+      ],
+      "Failed to create instance": [
+        "Fallo al crear la instancia"
+      ],
+      "Login required": [
+        "Login necesario"
+      ],
+      "Please enter your access token.": [
+        ""
+      ],
+      "Access Token": [
+        "Acceso denegado"
+      ],
+      "The request to the backend take too long and was cancelled": [
+        ""
+      ],
+      "Diagnostic from %1$s is \"%2$s\"": [
+        ""
+      ],
+      "The backend reported a problem: HTTP status #%1$s": [
+        "Servidir reporto un problema: HTTP status #%1$s"
+      ],
+      "Diagnostic from %1$s is '%2$s'": [
+        ""
+      ],
+      "Access denied": [
+        "Acceso denegado"
+      ],
+      "The access token provided is invalid.": [
+        ""
+      ],
+      "No 'default' instance configured yet.": [
+        "Sin instancia default"
+      ],
+      "Create a 'default' instance to begin using the merchant backoffice.": [
+        ""
+      ],
+      "The access token provided is invalid": [
+        ""
+      ],
+      "Hide for today": [
+        ""
+      ],
+      "Instance": [
+        "Instancia"
+      ],
+      "Settings": [
+        "Configuración"
+      ],
+      "Connection": [
+        "Conexión"
+      ],
+      "New": [
+        "Nuevo"
+      ],
+      "List": [
+        "Lista"
+      ],
+      "Log out": [
+        "Salir"
+      ],
+      "Check your token is valid": [
+        "Verifica que el token sea valido"
+      ],
+      "Couldn't access the server.": [
+        "No se pudo acceder al servidor."
+      ],
+      "Could not infer instance id from url %1$s": [
+        "No se pudo inferir el id de la instancia con la url %1$s"
+      ],
+      "Server not found": [
+        "Servidor no encontrado"
+      ],
+      "Server response with an error code": [
+        ""
+      ],
+      "Got message %1$s from %2$s": [
+        "Recibimos el mensaje %1$s desde %2$s"
+      ],
+      "Response from server is unreadable, http status: %1$s": [
+        ""
+      ],
+      "Unexpected Error": [
+        "Error inesperado"
+      ],
+      "The value %1$s is invalid for a payment url": [
+        "El valor %1$s es invalido para una URL de pago"
+      ],
+      "add element to the list": [
+        "agregar elemento a la lista"
+      ],
+      "add": [
+        "Agregar"
+      ],
+      "Deleting": [
+        "Borrando"
+      ],
+      "Changing": [
+        "Cambiando"
+      ],
+      "Order ID": [
+        "ID de pedido"
+      ],
+      "Payment URL": [
+        "URL de pago"
+      ]
+    }
+  }
+};
+
+strings['fr'] = {
+  "domain": "messages",
+  "locale_data": {
+    "messages": {
+      "": {
+        "domain": "messages",
+        "plural_forms": "nplurals=2; plural=(n != 1);",
+        "lang": ""
+      },
+      "Cancel": [
+        ""
+      ],
+      "%1$s": [
+        ""
+      ],
+      "Close": [
+        ""
+      ],
+      "Continue": [
+        ""
+      ],
+      "Clear": [
+        ""
+      ],
+      "Confirm": [
+        ""
+      ],
+      "is not the same as the current access token": [
+        ""
+      ],
+      "cannot be empty": [
+        ""
+      ],
+      "cannot be the same as the old token": [
+        ""
+      ],
+      "is not the same": [
+        ""
+      ],
+      "You are updating the access token from instance with id %1$s": [
+        ""
+      ],
+      "Old access token": [
+        ""
+      ],
+      "access token currently in use": [
+        ""
+      ],
+      "New access token": [
+        ""
+      ],
+      "next access token to be used": [
+        ""
+      ],
+      "Repeat access token": [
+        ""
+      ],
+      "confirm the same access token": [
+        ""
+      ],
+      "Clearing the access token will mean public access to the instance": [
+        ""
+      ],
+      "cannot be the same as the old access token": [
+        ""
+      ],
+      "You are setting the access token for the new instance": [
+        ""
+      ],
+      "With external authorization method no check will be done by the 
merchant backend": [
+        ""
+      ],
+      "Set external authorization": [
+        ""
+      ],
+      "Set access token": [
+        ""
+      ],
+      "Operation in progress...": [
+        ""
+      ],
+      "The operation will be automatically canceled after %1$s seconds": [
+        ""
+      ],
+      "Instances": [
+        ""
+      ],
+      "Delete": [
+        ""
+      ],
+      "add new instance": [
+        ""
+      ],
+      "ID": [
+        ""
+      ],
+      "Name": [
+        ""
+      ],
+      "Edit": [
+        ""
+      ],
+      "Purge": [
+        ""
+      ],
+      "There is no instances yet, add more pressing the + sign": [
+        ""
+      ],
+      "Only show active instances": [
+        ""
+      ],
+      "Active": [
+        ""
+      ],
+      "Only show deleted instances": [
+        ""
+      ],
+      "Deleted": [
+        ""
+      ],
+      "Show all instances": [
+        ""
+      ],
+      "All": [
+        ""
+      ],
+      "Instance \"%1$s\" (ID: %2$s) has been deleted": [
+        ""
+      ],
+      "Failed to delete instance": [
+        ""
+      ],
+      "Instance '%1$s' (ID: %2$s) has been disabled": [
+        ""
+      ],
+      "Failed to purge instance": [
+        ""
+      ],
+      "Pending KYC verification": [
+        ""
+      ],
+      "Timed out": [
+        ""
+      ],
+      "Exchange": [
+        ""
+      ],
+      "Target account": [
+        ""
+      ],
+      "KYC URL": [
+        ""
+      ],
+      "Code": [
+        ""
+      ],
+      "Http Status": [
+        ""
+      ],
+      "No pending kyc verification!": [
+        ""
+      ],
+      "change value to unknown date": [
+        ""
+      ],
+      "change value to empty": [
+        ""
+      ],
+      "clear": [
+        ""
+      ],
+      "change value to never": [
+        ""
+      ],
+      "never": [
+        ""
+      ],
+      "Country": [
+        ""
+      ],
+      "Address": [
+        ""
+      ],
+      "Building number": [
+        ""
+      ],
+      "Building name": [
+        ""
+      ],
+      "Street": [
+        ""
+      ],
+      "Post code": [
+        ""
+      ],
+      "Town location": [
+        ""
+      ],
+      "Town": [
+        ""
+      ],
+      "District": [
+        ""
+      ],
+      "Country subdivision": [
+        ""
+      ],
+      "Product id": [
+        ""
+      ],
+      "Description": [
+        ""
+      ],
+      "Product": [
+        ""
+      ],
+      "search products by it's description or id": [
+        ""
+      ],
+      "no products found with that description": [
+        ""
+      ],
+      "You must enter a valid product identifier.": [
+        ""
+      ],
+      "Quantity must be greater than 0!": [
+        ""
+      ],
+      "This quantity exceeds remaining stock. Currently, only %1$s units 
remain unreserved in stock.": [
+        ""
+      ],
+      "Quantity": [
+        ""
+      ],
+      "how many products will be added": [
+        ""
+      ],
+      "Add from inventory": [
+        ""
+      ],
+      "Image should be smaller than 1 MB": [
+        ""
+      ],
+      "Add": [
+        ""
+      ],
+      "Remove": [
+        ""
+      ],
+      "No taxes configured for this product.": [
+        ""
+      ],
+      "Amount": [
+        ""
+      ],
+      "Taxes can be in currencies that differ from the main currency used by 
the merchant.": [
+        ""
+      ],
+      "Enter currency and value separated with a colon, e.g. 
&quot;USD:2.3&quot;.": [
+        ""
+      ],
+      "Legal name of the tax, e.g. VAT or import duties.": [
+        ""
+      ],
+      "add tax to the tax list": [
+        ""
+      ],
+      "describe and add a product that is not in the inventory list": [
+        ""
+      ],
+      "Add custom product": [
+        ""
+      ],
+      "Complete information of the product": [
+        ""
+      ],
+      "Image": [
+        ""
+      ],
+      "photo of the product": [
+        ""
+      ],
+      "full product description": [
+        ""
+      ],
+      "Unit": [
+        ""
+      ],
+      "name of the product unit": [
+        ""
+      ],
+      "Price": [
+        ""
+      ],
+      "amount in the current currency": [
+        ""
+      ],
+      "Taxes": [
+        ""
+      ],
+      "image": [
+        ""
+      ],
+      "description": [
+        ""
+      ],
+      "quantity": [
+        ""
+      ],
+      "unit price": [
+        ""
+      ],
+      "total price": [
+        ""
+      ],
+      "required": [
+        ""
+      ],
+      "not valid": [
+        ""
+      ],
+      "must be greater than 0": [
+        ""
+      ],
+      "not a valid json": [
+        ""
+      ],
+      "should be in the future": [
+        ""
+      ],
+      "refund deadline cannot be before pay deadline": [
+        ""
+      ],
+      "wire transfer deadline cannot be before refund deadline": [
+        ""
+      ],
+      "wire transfer deadline cannot be before pay deadline": [
+        ""
+      ],
+      "should have a refund deadline": [
+        ""
+      ],
+      "auto refund cannot be after refund deadline": [
+        ""
+      ],
+      "Manage products in order": [
+        ""
+      ],
+      "Manage list of products in the order.": [
+        ""
+      ],
+      "Remove this product from the order.": [
+        ""
+      ],
+      "Total price": [
+        ""
+      ],
+      "total product price added up": [
+        ""
+      ],
+      "Amount to be paid by the customer": [
+        ""
+      ],
+      "Order price": [
+        ""
+      ],
+      "final order price": [
+        ""
+      ],
+      "Summary": [
+        ""
+      ],
+      "Title of the order to be shown to the customer": [
+        ""
+      ],
+      "Shipping and Fulfillment": [
+        ""
+      ],
+      "Delivery date": [
+        ""
+      ],
+      "Deadline for physical delivery assured by the merchant.": [
+        ""
+      ],
+      "Location": [
+        ""
+      ],
+      "address where the products will be delivered": [
+        ""
+      ],
+      "Fulfillment URL": [
+        ""
+      ],
+      "URL to which the user will be redirected after successful payment.": [
+        ""
+      ],
+      "Taler payment options": [
+        ""
+      ],
+      "Override default Taler payment settings for this order": [
+        ""
+      ],
+      "Payment deadline": [
+        ""
+      ],
+      "Deadline for the customer to pay for the offer before it expires. 
Inventory products will be reserved until this deadline.": [
+        ""
+      ],
+      "Refund deadline": [
+        ""
+      ],
+      "Time until which the order can be refunded by the merchant.": [
+        ""
+      ],
+      "Wire transfer deadline": [
+        ""
+      ],
+      "Deadline for the exchange to make the wire transfer.": [
+        ""
+      ],
+      "Auto-refund deadline": [
+        ""
+      ],
+      "Time until which the wallet will automatically check for refunds 
without user interaction.": [
+        ""
+      ],
+      "Maximum deposit fee": [
+        ""
+      ],
+      "Maximum deposit fees the merchant is willing to cover for this order. 
Higher deposit fees must be covered in full by the consumer.": [
+        ""
+      ],
+      "Maximum wire fee": [
+        ""
+      ],
+      "Maximum aggregate wire fees the merchant is willing to cover for this 
order. Wire fees exceeding this amount are to be covered by the customers.": [
+        ""
+      ],
+      "Wire fee amortization": [
+        ""
+      ],
+      "Factor by which wire fees exceeding the above threshold are divided to 
determine the share of excess wire fees to be paid explicitly by the 
consumer.": [
+        ""
+      ],
+      "Create token": [
+        ""
+      ],
+      "Uncheck this option if the merchant backend generated an order ID with 
enough entropy to prevent adversarial claims.": [
+        ""
+      ],
+      "Minimum age required": [
+        ""
+      ],
+      "Any value greater than 0 will limit the coins able be used to pay this 
contract. If empty the age restriction will be defined by the products": [
+        ""
+      ],
+      "Min age defined by the producs is %1$s": [
+        ""
+      ],
+      "Additional information": [
+        ""
+      ],
+      "Custom information to be included in the contract for this order.": [
+        ""
+      ],
+      "You must enter a value in JavaScript Object Notation (JSON).": [
+        ""
+      ],
+      "days": [
+        ""
+      ],
+      "hours": [
+        ""
+      ],
+      "minutes": [
+        ""
+      ],
+      "seconds": [
+        ""
+      ],
+      "forever": [
+        ""
+      ],
+      "%1$sM": [
+        ""
+      ],
+      "%1$sY": [
+        ""
+      ],
+      "%1$sd": [
+        ""
+      ],
+      "%1$sh": [
+        ""
+      ],
+      "%1$smin": [
+        ""
+      ],
+      "%1$ssec": [
+        ""
+      ],
+      "Orders": [
+        ""
+      ],
+      "create order": [
+        ""
+      ],
+      "load newer orders": [
+        ""
+      ],
+      "Date": [
+        ""
+      ],
+      "Refund": [
+        ""
+      ],
+      "copy url": [
+        ""
+      ],
+      "load older orders": [
+        ""
+      ],
+      "No orders have been found matching your query!": [
+        ""
+      ],
+      "duplicated": [
+        ""
+      ],
+      "invalid format": [
+        ""
+      ],
+      "this value exceed the refundable amount": [
+        ""
+      ],
+      "date": [
+        ""
+      ],
+      "amount": [
+        ""
+      ],
+      "reason": [
+        ""
+      ],
+      "amount to be refunded": [
+        ""
+      ],
+      "Max refundable:": [
+        ""
+      ],
+      "Reason": [
+        ""
+      ],
+      "Choose one...": [
+        ""
+      ],
+      "requested by the customer": [
+        ""
+      ],
+      "other": [
+        ""
+      ],
+      "why this order is being refunded": [
+        ""
+      ],
+      "more information to give context": [
+        ""
+      ],
+      "Contract Terms": [
+        ""
+      ],
+      "human-readable description of the whole purchase": [
+        ""
+      ],
+      "total price for the transaction": [
+        ""
+      ],
+      "URL for this purchase": [
+        ""
+      ],
+      "Max fee": [
+        ""
+      ],
+      "maximum total deposit fee accepted by the merchant for this contract": [
+        ""
+      ],
+      "Max wire fee": [
+        ""
+      ],
+      "maximum wire fee accepted by the merchant": [
+        ""
+      ],
+      "over how many customer transactions does the merchant expect to 
amortize wire fees on average": [
+        ""
+      ],
+      "Created at": [
+        ""
+      ],
+      "time when this contract was generated": [
+        ""
+      ],
+      "after this deadline has passed no refunds will be accepted": [
+        ""
+      ],
+      "after this deadline, the merchant won't accept payments for the 
contract": [
+        ""
+      ],
+      "transfer deadline for the exchange": [
+        ""
+      ],
+      "time indicating when the order should be delivered": [
+        ""
+      ],
+      "where the order will be delivered": [
+        ""
+      ],
+      "Auto-refund delay": [
+        ""
+      ],
+      "how long the wallet should try to get an automatic refund for the 
purchase": [
+        ""
+      ],
+      "Extra info": [
+        ""
+      ],
+      "extra data that is only interpreted by the merchant frontend": [
+        ""
+      ],
+      "Order": [
+        ""
+      ],
+      "claimed": [
+        ""
+      ],
+      "claimed at": [
+        ""
+      ],
+      "Timeline": [
+        ""
+      ],
+      "Payment details": [
+        ""
+      ],
+      "Order status": [
+        ""
+      ],
+      "Product list": [
+        ""
+      ],
+      "paid": [
+        ""
+      ],
+      "wired": [
+        ""
+      ],
+      "refunded": [
+        ""
+      ],
+      "refund order": [
+        ""
+      ],
+      "not refundable": [
+        ""
+      ],
+      "refund": [
+        ""
+      ],
+      "Refunded amount": [
+        ""
+      ],
+      "Refund taken": [
+        ""
+      ],
+      "Status URL": [
+        ""
+      ],
+      "Refund URI": [
+        ""
+      ],
+      "unpaid": [
+        ""
+      ],
+      "pay at": [
+        ""
+      ],
+      "created at": [
+        ""
+      ],
+      "Order status URL": [
+        ""
+      ],
+      "Payment URI": [
+        ""
+      ],
+      "Unknown order status. This is an error, please contact the 
administrator.": [
+        ""
+      ],
+      "Back": [
+        ""
+      ],
+      "refund created successfully": [
+        ""
+      ],
+      "could not create the refund": [
+        ""
+      ],
+      "select date to show nearby orders": [
+        ""
+      ],
+      "order id": [
+        ""
+      ],
+      "jump to order with the given order ID": [
+        ""
+      ],
+      "remove all filters": [
+        ""
+      ],
+      "only show paid orders": [
+        ""
+      ],
+      "Paid": [
+        ""
+      ],
+      "only show orders with refunds": [
+        ""
+      ],
+      "Refunded": [
+        ""
+      ],
+      "only show orders where customers paid, but wire payments from payment 
provider are still pending": [
+        ""
+      ],
+      "Not wired": [
+        ""
+      ],
+      "clear date filter": [
+        ""
+      ],
+      "date (YYYY/MM/DD)": [
+        ""
+      ],
+      "Enter an order id": [
+        ""
+      ],
+      "order not found": [
+        ""
+      ],
+      "could not get the order to refund": [
+        ""
+      ],
+      "Loading...": [
+        ""
+      ],
+      "click here to configure the stock of the product, leave it as is and 
the backend will not control stock": [
+        ""
+      ],
+      "Manage stock": [
+        ""
+      ],
+      "this product has been configured without stock control": [
+        ""
+      ],
+      "Infinite": [
+        ""
+      ],
+      "lost cannot be greater than current and incoming (max %1$s)": [
+        ""
+      ],
+      "Incoming": [
+        ""
+      ],
+      "Lost": [
+        ""
+      ],
+      "Current": [
+        ""
+      ],
+      "remove stock control for this product": [
+        ""
+      ],
+      "without stock": [
+        ""
+      ],
+      "Next restock": [
+        ""
+      ],
+      "Delivery address": [
+        ""
+      ],
+      "product identification to use in URLs (for internal use only)": [
+        ""
+      ],
+      "illustration of the product for customers": [
+        ""
+      ],
+      "product description for customers": [
+        ""
+      ],
+      "Age restricted": [
+        ""
+      ],
+      "is this product restricted for customer below certain age?": [
+        ""
+      ],
+      "unit describing quantity of product sold (e.g. 2 kilograms, 5 liters, 3 
items, 5 meters) for customers": [
+        ""
+      ],
+      "sale price for customers, including taxes, for above units of the 
product": [
+        ""
+      ],
+      "Stock": [
+        ""
+      ],
+      "product inventory for products with finite supply (for internal use 
only)": [
+        ""
+      ],
+      "taxes included in the product price, exposed to customers": [
+        ""
+      ],
+      "Need to complete marked fields": [
+        ""
+      ],
+      "could not create product": [
+        ""
+      ],
+      "Products": [
+        ""
+      ],
+      "add product to inventory": [
+        ""
+      ],
+      "Sell": [
+        ""
+      ],
+      "Profit": [
+        ""
+      ],
+      "Sold": [
+        ""
+      ],
+      "free": [
+        ""
+      ],
+      "go to product update page": [
+        ""
+      ],
+      "Update": [
+        ""
+      ],
+      "remove this product from the database": [
+        ""
+      ],
+      "update the product with new price": [
+        ""
+      ],
+      "update product with new price": [
+        ""
+      ],
+      "add more elements to the inventory": [
+        ""
+      ],
+      "report elements lost in the inventory": [
+        ""
+      ],
+      "new price for the product": [
+        ""
+      ],
+      "the are value with errors": [
+        ""
+      ],
+      "update product with new stock and price": [
+        ""
+      ],
+      "There is no products yet, add more pressing the + sign": [
+        ""
+      ],
+      "product updated successfully": [
+        ""
+      ],
+      "could not update the product": [
+        ""
+      ],
+      "product delete successfully": [
+        ""
+      ],
+      "could not delete the product": [
+        ""
+      ],
+      "Product id:": [
+        ""
+      ],
+      "To complete the setup of the reserve, you must now initiate a wire 
transfer using the given wire transfer subject and crediting the specified 
amount to the indicated account of the exchange.": [
+        ""
+      ],
+      "If your system supports RFC 8905, you can do this by opening this 
URI:": [
+        ""
+      ],
+      "it should be greater than 0": [
+        ""
+      ],
+      "must be a valid URL": [
+        ""
+      ],
+      "Initial balance": [
+        ""
+      ],
+      "balance prior to deposit": [
+        ""
+      ],
+      "Exchange URL": [
+        ""
+      ],
+      "URL of exchange": [
+        ""
+      ],
+      "Next": [
+        ""
+      ],
+      "Wire method": [
+        ""
+      ],
+      "method to use for wire transfer": [
+        ""
+      ],
+      "Select one wire method": [
+        ""
+      ],
+      "could not create reserve": [
+        ""
+      ],
+      "Valid until": [
+        ""
+      ],
+      "Created balance": [
+        ""
+      ],
+      "Exchange balance": [
+        ""
+      ],
+      "Picked up": [
+        ""
+      ],
+      "Committed": [
+        ""
+      ],
+      "Account address": [
+        ""
+      ],
+      "Subject": [
+        ""
+      ],
+      "Tips": [
+        ""
+      ],
+      "No tips has been authorized from this reserve": [
+        ""
+      ],
+      "Authorized": [
+        ""
+      ],
+      "Expiration": [
+        ""
+      ],
+      "amount of tip": [
+        ""
+      ],
+      "Justification": [
+        ""
+      ],
+      "reason for the tip": [
+        ""
+      ],
+      "URL after tip": [
+        ""
+      ],
+      "URL to visit after tip payment": [
+        ""
+      ],
+      "Reserves not yet funded": [
+        ""
+      ],
+      "Reserves ready": [
+        ""
+      ],
+      "add new reserve": [
+        ""
+      ],
+      "Expires at": [
+        ""
+      ],
+      "Initial": [
+        ""
+      ],
+      "delete selected reserve from the database": [
+        ""
+      ],
+      "authorize new tip from selected reserve": [
+        ""
+      ],
+      "There is no ready reserves yet, add more pressing the + sign or fund 
them": [
+        ""
+      ],
+      "Expected Balance": [
+        ""
+      ],
+      "could not create the tip": [
+        ""
+      ],
+      "should not be empty": [
+        ""
+      ],
+      "should be greater that 0": [
+        ""
+      ],
+      "can't be empty": [
+        ""
+      ],
+      "to short": [
+        ""
+      ],
+      "just letters and numbers from 2 to 7": [
+        ""
+      ],
+      "size of the key should be 32": [
+        ""
+      ],
+      "Identifier": [
+        ""
+      ],
+      "Name of the template in URLs.": [
+        ""
+      ],
+      "Describe what this template stands for": [
+        ""
+      ],
+      "Fixed summary": [
+        ""
+      ],
+      "If specified, this template will create order with the same summary": [
+        ""
+      ],
+      "Fixed price": [
+        ""
+      ],
+      "If specified, this template will create order with the same price": [
+        ""
+      ],
+      "Minimum age": [
+        ""
+      ],
+      "Is this contract restricted to some age?": [
+        ""
+      ],
+      "Payment timeout": [
+        ""
+      ],
+      "How much time has the customer to complete the payment once the order 
was created.": [
+        ""
+      ],
+      "Verification algorithm": [
+        ""
+      ],
+      "Algorithm to use to verify transaction in offline mode": [
+        ""
+      ],
+      "Point-of-sale key": [
+        ""
+      ],
+      "Useful to validate the purchase": [
+        ""
+      ],
+      "generate random secret key": [
+        ""
+      ],
+      "random": [
+        ""
+      ],
+      "show secret key": [
+        ""
+      ],
+      "hide secret key": [
+        ""
+      ],
+      "hide": [
+        ""
+      ],
+      "show": [
+        ""
+      ],
+      "could not inform template": [
+        ""
+      ],
+      "Amount is required": [
+        ""
+      ],
+      "Order summary is required": [
+        ""
+      ],
+      "New order for template": [
+        ""
+      ],
+      "Amount of the order": [
+        ""
+      ],
+      "Order summary": [
+        ""
+      ],
+      "could not create order from template": [
+        ""
+      ],
+      "Here you can specify a default value for fields that are not fixed. 
Default values can be edited by the customer before the payment.": [
+        ""
+      ],
+      "Fixed amount": [
+        ""
+      ],
+      "Default amount": [
+        ""
+      ],
+      "Default summary": [
+        ""
+      ],
+      "Print": [
+        ""
+      ],
+      "Setup TOTP": [
+        ""
+      ],
+      "Templates": [
+        ""
+      ],
+      "add new templates": [
+        ""
+      ],
+      "load more templates before the first one": [
+        ""
+      ],
+      "load newer templates": [
+        ""
+      ],
+      "delete selected templates from the database": [
+        ""
+      ],
+      "use template to create new order": [
+        ""
+      ],
+      "create qr code for the template": [
+        ""
+      ],
+      "load more templates after the last one": [
+        ""
+      ],
+      "load older templates": [
+        ""
+      ],
+      "There is no templates yet, add more pressing the + sign": [
+        ""
+      ],
+      "template delete successfully": [
+        ""
+      ],
+      "could not delete the template": [
+        ""
+      ],
+      "could not update template": [
+        ""
+      ],
+      "should be one of '%1$s'": [
+        ""
+      ],
+      "Webhook ID to use": [
+        ""
+      ],
+      "Event": [
+        ""
+      ],
+      "The event of the webhook: why the webhook is used": [
+        ""
+      ],
+      "Method": [
+        ""
+      ],
+      "Method used by the webhook": [
+        ""
+      ],
+      "URL": [
+        ""
+      ],
+      "URL of the webhook where the customer will be redirected": [
+        ""
+      ],
+      "Header": [
+        ""
+      ],
+      "Header template of the webhook": [
+        ""
+      ],
+      "Body": [
+        ""
+      ],
+      "Body template by the webhook": [
+        ""
+      ],
+      "Webhooks": [
+        ""
+      ],
+      "add new webhooks": [
+        ""
+      ],
+      "load more webhooks before the first one": [
+        ""
+      ],
+      "load newer webhooks": [
+        ""
+      ],
+      "Event type": [
+        ""
+      ],
+      "delete selected webhook from the database": [
+        ""
+      ],
+      "load more webhooks after the last one": [
+        ""
+      ],
+      "load older webhooks": [
+        ""
+      ],
+      "There is no webhooks yet, add more pressing the + sign": [
+        ""
+      ],
+      "webhook delete successfully": [
+        ""
+      ],
+      "could not delete the webhook": [
+        ""
+      ],
+      "check the id, does not look valid": [
+        ""
+      ],
+      "should have 52 characters, current %1$s": [
+        ""
+      ],
+      "URL doesn't have the right format": [
+        ""
+      ],
+      "Credited bank account": [
+        ""
+      ],
+      "Select one account": [
+        ""
+      ],
+      "Bank account of the merchant where the payment was received": [
+        ""
+      ],
+      "Wire transfer ID": [
+        ""
+      ],
+      "unique identifier of the wire transfer used by the exchange, must be 52 
characters long": [
+        ""
+      ],
+      "Base URL of the exchange that made the transfer, should have been in 
the wire transfer subject": [
+        ""
+      ],
+      "Amount credited": [
+        ""
+      ],
+      "Actual amount that was wired to the merchant's bank account": [
+        ""
+      ],
+      "could not inform transfer": [
+        ""
+      ],
+      "Transfers": [
+        ""
+      ],
+      "add new transfer": [
+        ""
+      ],
+      "load more transfers before the first one": [
+        ""
+      ],
+      "load newer transfers": [
+        ""
+      ],
+      "Credit": [
+        ""
+      ],
+      "Confirmed": [
+        ""
+      ],
+      "Verified": [
+        ""
+      ],
+      "Executed at": [
+        ""
+      ],
+      "yes": [
+        ""
+      ],
+      "no": [
+        ""
+      ],
+      "unknown": [
+        ""
+      ],
+      "delete selected transfer from the database": [
+        ""
+      ],
+      "load more transfer after the last one": [
+        ""
+      ],
+      "load older transfers": [
+        ""
+      ],
+      "There is no transfer yet, add more pressing the + sign": [
+        ""
+      ],
+      "filter by account address": [
+        ""
+      ],
+      "only show wire transfers confirmed by the merchant": [
+        ""
+      ],
+      "only show wire transfers claimed by the exchange": [
+        ""
+      ],
+      "Unverified": [
+        ""
+      ],
+      "is not valid": [
+        ""
+      ],
+      "is not a number": [
+        ""
+      ],
+      "must be 1 or greater": [
+        ""
+      ],
+      "max 7 lines": [
+        ""
+      ],
+      "change authorization configuration": [
+        ""
+      ],
+      "Need to complete marked fields and choose authorization method": [
+        ""
+      ],
+      "This is not a valid bitcoin address.": [
+        ""
+      ],
+      "This is not a valid Ethereum address.": [
+        ""
+      ],
+      "IBAN numbers usually have more that 4 digits": [
+        ""
+      ],
+      "IBAN numbers usually have less that 34 digits": [
+        ""
+      ],
+      "IBAN country code not found": [
+        ""
+      ],
+      "IBAN number is not valid, checksum is wrong": [
+        ""
+      ],
+      "Target type": [
+        ""
+      ],
+      "Method to use for wire transfer": [
+        ""
+      ],
+      "Routing": [
+        ""
+      ],
+      "Routing number.": [
+        ""
+      ],
+      "Account": [
+        ""
+      ],
+      "Account number.": [
+        ""
+      ],
+      "Business Identifier Code.": [
+        ""
+      ],
+      "Bank Account Number.": [
+        ""
+      ],
+      "Unified Payment Interface.": [
+        ""
+      ],
+      "Bitcoin protocol.": [
+        ""
+      ],
+      "Ethereum protocol.": [
+        ""
+      ],
+      "Interledger protocol.": [
+        ""
+      ],
+      "Host": [
+        ""
+      ],
+      "Bank host.": [
+        ""
+      ],
+      "Bank account.": [
+        ""
+      ],
+      "Bank account owner's name.": [
+        ""
+      ],
+      "No accounts yet.": [
+        ""
+      ],
+      "Name of the instance in URLs. The 'default' instance is special in that 
it is used to administer other instances.": [
+        ""
+      ],
+      "Business name": [
+        ""
+      ],
+      "Legal name of the business represented by this instance.": [
+        ""
+      ],
+      "Email": [
+        ""
+      ],
+      "Contact email": [
+        ""
+      ],
+      "Website URL": [
+        ""
+      ],
+      "URL.": [
+        ""
+      ],
+      "Logo": [
+        ""
+      ],
+      "Logo image.": [
+        ""
+      ],
+      "Bank account": [
+        ""
+      ],
+      "URI specifying bank account for crediting revenue.": [
+        ""
+      ],
+      "Default max deposit fee": [
+        ""
+      ],
+      "Maximum deposit fees this merchant is willing to pay per order by 
default.": [
+        ""
+      ],
+      "Default max wire fee": [
+        ""
+      ],
+      "Maximum wire fees this merchant is willing to pay per wire transfer by 
default.": [
+        ""
+      ],
+      "Default wire fee amortization": [
+        ""
+      ],
+      "Number of orders excess wire transfer fees will be divided by to 
compute per order surcharge.": [
+        ""
+      ],
+      "Physical location of the merchant.": [
+        ""
+      ],
+      "Jurisdiction": [
+        ""
+      ],
+      "Jurisdiction for legal disputes with the merchant.": [
+        ""
+      ],
+      "Default payment delay": [
+        ""
+      ],
+      "Time customers have to pay an order before the offer expires by 
default.": [
+        ""
+      ],
+      "Default wire transfer delay": [
+        ""
+      ],
+      "Maximum time an exchange is allowed to delay wiring funds to the 
merchant, enabling it to aggregate smaller payments into larger wire transfers 
and reducing wire fees.": [
+        ""
+      ],
+      "Instance id": [
+        ""
+      ],
+      "Change the authorization method use for this instance.": [
+        ""
+      ],
+      "Manage access token": [
+        ""
+      ],
+      "Failed to create instance": [
+        ""
+      ],
+      "Login required": [
+        ""
+      ],
+      "Please enter your access token.": [
+        ""
+      ],
+      "Access Token": [
+        ""
+      ],
+      "The request to the backend take too long and was cancelled": [
+        ""
+      ],
+      "Diagnostic from %1$s is \"%2$s\"": [
+        ""
+      ],
+      "The backend reported a problem: HTTP status #%1$s": [
+        ""
+      ],
+      "Diagnostic from %1$s is '%2$s'": [
+        ""
+      ],
+      "Access denied": [
+        ""
+      ],
+      "The access token provided is invalid.": [
+        ""
+      ],
+      "No 'default' instance configured yet.": [
+        ""
+      ],
+      "Create a 'default' instance to begin using the merchant backoffice.": [
+        ""
+      ],
+      "The access token provided is invalid": [
+        ""
+      ],
+      "Hide for today": [
+        ""
+      ],
+      "Instance": [
+        ""
+      ],
+      "Settings": [
+        ""
+      ],
+      "Connection": [
+        ""
+      ],
+      "New": [
+        ""
+      ],
+      "List": [
+        ""
+      ],
+      "Log out": [
+        ""
+      ],
+      "Check your token is valid": [
+        ""
+      ],
+      "Couldn't access the server.": [
+        ""
+      ],
+      "Could not infer instance id from url %1$s": [
+        ""
+      ],
+      "Server not found": [
+        ""
+      ],
+      "Server response with an error code": [
+        ""
+      ],
+      "Got message %1$s from %2$s": [
+        ""
+      ],
+      "Response from server is unreadable, http status: %1$s": [
+        ""
+      ],
+      "Unexpected Error": [
+        ""
+      ],
+      "The value %1$s is invalid for a payment url": [
+        ""
+      ],
+      "add element to the list": [
+        ""
+      ],
+      "add": [
+        ""
+      ],
+      "Deleting": [
+        ""
+      ],
+      "Changing": [
+        ""
+      ],
+      "Order ID": [
+        ""
+      ],
+      "Payment URL": [
+        ""
+      ]
+    }
+  }
+};
+
+strings['it'] = {
+  "domain": "messages",
+  "locale_data": {
+    "messages": {
+      "": {
+        "domain": "messages",
+        "plural_forms": "nplurals=2; plural=(n != 1);",
+        "lang": ""
+      },
+      "Cancel": [
+        ""
+      ],
+      "%1$s": [
+        ""
+      ],
+      "Close": [
+        ""
+      ],
+      "Continue": [
+        ""
+      ],
+      "Clear": [
+        ""
+      ],
+      "Confirm": [
+        ""
+      ],
+      "is not the same as the current access token": [
+        ""
+      ],
+      "cannot be empty": [
+        ""
+      ],
+      "cannot be the same as the old token": [
+        ""
+      ],
+      "is not the same": [
+        ""
+      ],
+      "You are updating the access token from instance with id %1$s": [
+        ""
+      ],
+      "Old access token": [
+        ""
+      ],
+      "access token currently in use": [
+        ""
+      ],
+      "New access token": [
+        ""
+      ],
+      "next access token to be used": [
+        ""
+      ],
+      "Repeat access token": [
+        ""
+      ],
+      "confirm the same access token": [
+        ""
+      ],
+      "Clearing the access token will mean public access to the instance": [
+        ""
+      ],
+      "cannot be the same as the old access token": [
+        ""
+      ],
+      "You are setting the access token for the new instance": [
+        ""
+      ],
+      "With external authorization method no check will be done by the 
merchant backend": [
+        ""
+      ],
+      "Set external authorization": [
+        ""
+      ],
+      "Set access token": [
+        ""
+      ],
+      "Operation in progress...": [
+        ""
+      ],
+      "The operation will be automatically canceled after %1$s seconds": [
+        ""
+      ],
+      "Instances": [
+        ""
+      ],
+      "Delete": [
+        ""
+      ],
+      "add new instance": [
+        ""
+      ],
+      "ID": [
+        ""
+      ],
+      "Name": [
+        ""
+      ],
+      "Edit": [
+        ""
+      ],
+      "Purge": [
+        ""
+      ],
+      "There is no instances yet, add more pressing the + sign": [
+        ""
+      ],
+      "Only show active instances": [
+        ""
+      ],
+      "Active": [
+        ""
+      ],
+      "Only show deleted instances": [
+        ""
+      ],
+      "Deleted": [
+        ""
+      ],
+      "Show all instances": [
+        ""
+      ],
+      "All": [
+        ""
+      ],
+      "Instance \"%1$s\" (ID: %2$s) has been deleted": [
+        ""
+      ],
+      "Failed to delete instance": [
+        ""
+      ],
+      "Instance '%1$s' (ID: %2$s) has been disabled": [
+        ""
+      ],
+      "Failed to purge instance": [
+        ""
+      ],
+      "Pending KYC verification": [
+        ""
+      ],
+      "Timed out": [
+        ""
+      ],
+      "Exchange": [
+        ""
+      ],
+      "Target account": [
+        ""
+      ],
+      "KYC URL": [
+        ""
+      ],
+      "Code": [
+        ""
+      ],
+      "Http Status": [
+        ""
+      ],
+      "No pending kyc verification!": [
+        ""
+      ],
+      "change value to unknown date": [
+        ""
+      ],
+      "change value to empty": [
+        ""
+      ],
+      "clear": [
+        ""
+      ],
+      "change value to never": [
+        ""
+      ],
+      "never": [
+        ""
+      ],
+      "Country": [
+        ""
+      ],
+      "Address": [
+        ""
+      ],
+      "Building number": [
+        ""
+      ],
+      "Building name": [
+        ""
+      ],
+      "Street": [
+        ""
+      ],
+      "Post code": [
+        ""
+      ],
+      "Town location": [
+        ""
+      ],
+      "Town": [
+        ""
+      ],
+      "District": [
+        ""
+      ],
+      "Country subdivision": [
+        ""
+      ],
+      "Product id": [
+        ""
+      ],
+      "Description": [
+        ""
+      ],
+      "Product": [
+        ""
+      ],
+      "search products by it's description or id": [
+        ""
+      ],
+      "no products found with that description": [
+        ""
+      ],
+      "You must enter a valid product identifier.": [
+        ""
+      ],
+      "Quantity must be greater than 0!": [
+        ""
+      ],
+      "This quantity exceeds remaining stock. Currently, only %1$s units 
remain unreserved in stock.": [
+        ""
+      ],
+      "Quantity": [
+        ""
+      ],
+      "how many products will be added": [
+        ""
+      ],
+      "Add from inventory": [
+        ""
+      ],
+      "Image should be smaller than 1 MB": [
+        ""
+      ],
+      "Add": [
+        ""
+      ],
+      "Remove": [
+        ""
+      ],
+      "No taxes configured for this product.": [
+        ""
+      ],
+      "Amount": [
+        ""
+      ],
+      "Taxes can be in currencies that differ from the main currency used by 
the merchant.": [
+        ""
+      ],
+      "Enter currency and value separated with a colon, e.g. 
&quot;USD:2.3&quot;.": [
+        ""
+      ],
+      "Legal name of the tax, e.g. VAT or import duties.": [
+        ""
+      ],
+      "add tax to the tax list": [
+        ""
+      ],
+      "describe and add a product that is not in the inventory list": [
+        ""
+      ],
+      "Add custom product": [
+        ""
+      ],
+      "Complete information of the product": [
+        ""
+      ],
+      "Image": [
+        ""
+      ],
+      "photo of the product": [
+        ""
+      ],
+      "full product description": [
+        ""
+      ],
+      "Unit": [
+        ""
+      ],
+      "name of the product unit": [
+        ""
+      ],
+      "Price": [
+        ""
+      ],
+      "amount in the current currency": [
+        ""
+      ],
+      "Taxes": [
+        ""
+      ],
+      "image": [
+        ""
+      ],
+      "description": [
+        ""
+      ],
+      "quantity": [
+        ""
+      ],
+      "unit price": [
+        ""
+      ],
+      "total price": [
+        ""
+      ],
+      "required": [
+        ""
+      ],
+      "not valid": [
+        ""
+      ],
+      "must be greater than 0": [
+        ""
+      ],
+      "not a valid json": [
+        ""
+      ],
+      "should be in the future": [
+        ""
+      ],
+      "refund deadline cannot be before pay deadline": [
+        ""
+      ],
+      "wire transfer deadline cannot be before refund deadline": [
+        ""
+      ],
+      "wire transfer deadline cannot be before pay deadline": [
+        ""
+      ],
+      "should have a refund deadline": [
+        ""
+      ],
+      "auto refund cannot be after refund deadline": [
+        ""
+      ],
+      "Manage products in order": [
+        ""
+      ],
+      "Manage list of products in the order.": [
+        ""
+      ],
+      "Remove this product from the order.": [
+        ""
+      ],
+      "Total price": [
+        ""
+      ],
+      "total product price added up": [
+        ""
+      ],
+      "Amount to be paid by the customer": [
+        ""
+      ],
+      "Order price": [
+        ""
+      ],
+      "final order price": [
+        ""
+      ],
+      "Summary": [
+        ""
+      ],
+      "Title of the order to be shown to the customer": [
+        ""
+      ],
+      "Shipping and Fulfillment": [
+        ""
+      ],
+      "Delivery date": [
+        ""
+      ],
+      "Deadline for physical delivery assured by the merchant.": [
+        ""
+      ],
+      "Location": [
+        ""
+      ],
+      "address where the products will be delivered": [
+        ""
+      ],
+      "Fulfillment URL": [
+        ""
+      ],
+      "URL to which the user will be redirected after successful payment.": [
+        ""
+      ],
+      "Taler payment options": [
+        ""
+      ],
+      "Override default Taler payment settings for this order": [
+        ""
+      ],
+      "Payment deadline": [
+        ""
+      ],
+      "Deadline for the customer to pay for the offer before it expires. 
Inventory products will be reserved until this deadline.": [
+        ""
+      ],
+      "Refund deadline": [
+        ""
+      ],
+      "Time until which the order can be refunded by the merchant.": [
+        ""
+      ],
+      "Wire transfer deadline": [
+        ""
+      ],
+      "Deadline for the exchange to make the wire transfer.": [
+        ""
+      ],
+      "Auto-refund deadline": [
+        ""
+      ],
+      "Time until which the wallet will automatically check for refunds 
without user interaction.": [
+        ""
+      ],
+      "Maximum deposit fee": [
+        ""
+      ],
+      "Maximum deposit fees the merchant is willing to cover for this order. 
Higher deposit fees must be covered in full by the consumer.": [
+        ""
+      ],
+      "Maximum wire fee": [
+        ""
+      ],
+      "Maximum aggregate wire fees the merchant is willing to cover for this 
order. Wire fees exceeding this amount are to be covered by the customers.": [
+        ""
+      ],
+      "Wire fee amortization": [
+        ""
+      ],
+      "Factor by which wire fees exceeding the above threshold are divided to 
determine the share of excess wire fees to be paid explicitly by the 
consumer.": [
+        ""
+      ],
+      "Create token": [
+        ""
+      ],
+      "Uncheck this option if the merchant backend generated an order ID with 
enough entropy to prevent adversarial claims.": [
+        ""
+      ],
+      "Minimum age required": [
+        ""
+      ],
+      "Any value greater than 0 will limit the coins able be used to pay this 
contract. If empty the age restriction will be defined by the products": [
+        ""
+      ],
+      "Min age defined by the producs is %1$s": [
+        ""
+      ],
+      "Additional information": [
+        ""
+      ],
+      "Custom information to be included in the contract for this order.": [
+        ""
+      ],
+      "You must enter a value in JavaScript Object Notation (JSON).": [
+        ""
+      ],
+      "days": [
+        ""
+      ],
+      "hours": [
+        ""
+      ],
+      "minutes": [
+        ""
+      ],
+      "seconds": [
+        ""
+      ],
+      "forever": [
+        ""
+      ],
+      "%1$sM": [
+        ""
+      ],
+      "%1$sY": [
+        ""
+      ],
+      "%1$sd": [
+        ""
+      ],
+      "%1$sh": [
+        ""
+      ],
+      "%1$smin": [
+        ""
+      ],
+      "%1$ssec": [
+        ""
+      ],
+      "Orders": [
+        ""
+      ],
+      "create order": [
+        ""
+      ],
+      "load newer orders": [
+        ""
+      ],
+      "Date": [
+        ""
+      ],
+      "Refund": [
+        ""
+      ],
+      "copy url": [
+        ""
+      ],
+      "load older orders": [
+        ""
+      ],
+      "No orders have been found matching your query!": [
+        ""
+      ],
+      "duplicated": [
+        ""
+      ],
+      "invalid format": [
+        ""
+      ],
+      "this value exceed the refundable amount": [
+        ""
+      ],
+      "date": [
+        ""
+      ],
+      "amount": [
+        ""
+      ],
+      "reason": [
+        ""
+      ],
+      "amount to be refunded": [
+        ""
+      ],
+      "Max refundable:": [
+        ""
+      ],
+      "Reason": [
+        ""
+      ],
+      "Choose one...": [
+        ""
+      ],
+      "requested by the customer": [
+        ""
+      ],
+      "other": [
+        ""
+      ],
+      "why this order is being refunded": [
+        ""
+      ],
+      "more information to give context": [
+        ""
+      ],
+      "Contract Terms": [
+        ""
+      ],
+      "human-readable description of the whole purchase": [
+        ""
+      ],
+      "total price for the transaction": [
+        ""
+      ],
+      "URL for this purchase": [
+        ""
+      ],
+      "Max fee": [
+        ""
+      ],
+      "maximum total deposit fee accepted by the merchant for this contract": [
+        ""
+      ],
+      "Max wire fee": [
+        ""
+      ],
+      "maximum wire fee accepted by the merchant": [
+        ""
+      ],
+      "over how many customer transactions does the merchant expect to 
amortize wire fees on average": [
+        ""
+      ],
+      "Created at": [
+        ""
+      ],
+      "time when this contract was generated": [
+        ""
+      ],
+      "after this deadline has passed no refunds will be accepted": [
+        ""
+      ],
+      "after this deadline, the merchant won't accept payments for the 
contract": [
+        ""
+      ],
+      "transfer deadline for the exchange": [
+        ""
+      ],
+      "time indicating when the order should be delivered": [
+        ""
+      ],
+      "where the order will be delivered": [
+        ""
+      ],
+      "Auto-refund delay": [
+        ""
+      ],
+      "how long the wallet should try to get an automatic refund for the 
purchase": [
+        ""
+      ],
+      "Extra info": [
+        ""
+      ],
+      "extra data that is only interpreted by the merchant frontend": [
+        ""
+      ],
+      "Order": [
+        ""
+      ],
+      "claimed": [
+        ""
+      ],
+      "claimed at": [
+        ""
+      ],
+      "Timeline": [
+        ""
+      ],
+      "Payment details": [
+        ""
+      ],
+      "Order status": [
+        ""
+      ],
+      "Product list": [
+        ""
+      ],
+      "paid": [
+        ""
+      ],
+      "wired": [
+        ""
+      ],
+      "refunded": [
+        ""
+      ],
+      "refund order": [
+        ""
+      ],
+      "not refundable": [
+        ""
+      ],
+      "refund": [
+        ""
+      ],
+      "Refunded amount": [
+        ""
+      ],
+      "Refund taken": [
+        ""
+      ],
+      "Status URL": [
+        ""
+      ],
+      "Refund URI": [
+        ""
+      ],
+      "unpaid": [
+        ""
+      ],
+      "pay at": [
+        ""
+      ],
+      "created at": [
+        ""
+      ],
+      "Order status URL": [
+        ""
+      ],
+      "Payment URI": [
+        ""
+      ],
+      "Unknown order status. This is an error, please contact the 
administrator.": [
+        ""
+      ],
+      "Back": [
+        ""
+      ],
+      "refund created successfully": [
+        ""
+      ],
+      "could not create the refund": [
+        ""
+      ],
+      "select date to show nearby orders": [
+        ""
+      ],
+      "order id": [
+        ""
+      ],
+      "jump to order with the given order ID": [
+        ""
+      ],
+      "remove all filters": [
+        ""
+      ],
+      "only show paid orders": [
+        ""
+      ],
+      "Paid": [
+        ""
+      ],
+      "only show orders with refunds": [
+        ""
+      ],
+      "Refunded": [
+        ""
+      ],
+      "only show orders where customers paid, but wire payments from payment 
provider are still pending": [
+        ""
+      ],
+      "Not wired": [
+        ""
+      ],
+      "clear date filter": [
+        ""
+      ],
+      "date (YYYY/MM/DD)": [
+        ""
+      ],
+      "Enter an order id": [
+        ""
+      ],
+      "order not found": [
+        ""
+      ],
+      "could not get the order to refund": [
+        ""
+      ],
+      "Loading...": [
+        ""
+      ],
+      "click here to configure the stock of the product, leave it as is and 
the backend will not control stock": [
+        ""
+      ],
+      "Manage stock": [
+        ""
+      ],
+      "this product has been configured without stock control": [
+        ""
+      ],
+      "Infinite": [
+        ""
+      ],
+      "lost cannot be greater than current and incoming (max %1$s)": [
+        ""
+      ],
+      "Incoming": [
+        ""
+      ],
+      "Lost": [
+        ""
+      ],
+      "Current": [
+        ""
+      ],
+      "remove stock control for this product": [
+        ""
+      ],
+      "without stock": [
+        ""
+      ],
+      "Next restock": [
+        ""
+      ],
+      "Delivery address": [
+        ""
+      ],
+      "product identification to use in URLs (for internal use only)": [
+        ""
+      ],
+      "illustration of the product for customers": [
+        ""
+      ],
+      "product description for customers": [
+        ""
+      ],
+      "Age restricted": [
+        ""
+      ],
+      "is this product restricted for customer below certain age?": [
+        ""
+      ],
+      "unit describing quantity of product sold (e.g. 2 kilograms, 5 liters, 3 
items, 5 meters) for customers": [
+        ""
+      ],
+      "sale price for customers, including taxes, for above units of the 
product": [
+        ""
+      ],
+      "Stock": [
+        ""
+      ],
+      "product inventory for products with finite supply (for internal use 
only)": [
+        ""
+      ],
+      "taxes included in the product price, exposed to customers": [
+        ""
+      ],
+      "Need to complete marked fields": [
+        ""
+      ],
+      "could not create product": [
+        ""
+      ],
+      "Products": [
+        ""
+      ],
+      "add product to inventory": [
+        ""
+      ],
+      "Sell": [
+        ""
+      ],
+      "Profit": [
+        ""
+      ],
+      "Sold": [
+        ""
+      ],
+      "free": [
+        ""
+      ],
+      "go to product update page": [
+        ""
+      ],
+      "Update": [
+        ""
+      ],
+      "remove this product from the database": [
+        ""
+      ],
+      "update the product with new price": [
+        ""
+      ],
+      "update product with new price": [
+        ""
+      ],
+      "add more elements to the inventory": [
+        ""
+      ],
+      "report elements lost in the inventory": [
+        ""
+      ],
+      "new price for the product": [
+        ""
+      ],
+      "the are value with errors": [
+        ""
+      ],
+      "update product with new stock and price": [
+        ""
+      ],
+      "There is no products yet, add more pressing the + sign": [
+        ""
+      ],
+      "product updated successfully": [
+        ""
+      ],
+      "could not update the product": [
+        ""
+      ],
+      "product delete successfully": [
+        ""
+      ],
+      "could not delete the product": [
+        ""
+      ],
+      "Product id:": [
+        ""
+      ],
+      "To complete the setup of the reserve, you must now initiate a wire 
transfer using the given wire transfer subject and crediting the specified 
amount to the indicated account of the exchange.": [
+        ""
+      ],
+      "If your system supports RFC 8905, you can do this by opening this 
URI:": [
+        ""
+      ],
+      "it should be greater than 0": [
+        ""
+      ],
+      "must be a valid URL": [
+        ""
+      ],
+      "Initial balance": [
+        ""
+      ],
+      "balance prior to deposit": [
+        ""
+      ],
+      "Exchange URL": [
+        ""
+      ],
+      "URL of exchange": [
+        ""
+      ],
+      "Next": [
+        ""
+      ],
+      "Wire method": [
+        ""
+      ],
+      "method to use for wire transfer": [
+        ""
+      ],
+      "Select one wire method": [
+        ""
+      ],
+      "could not create reserve": [
+        ""
+      ],
+      "Valid until": [
+        ""
+      ],
+      "Created balance": [
+        ""
+      ],
+      "Exchange balance": [
+        ""
+      ],
+      "Picked up": [
+        ""
+      ],
+      "Committed": [
+        ""
+      ],
+      "Account address": [
+        ""
+      ],
+      "Subject": [
+        ""
+      ],
+      "Tips": [
+        ""
+      ],
+      "No tips has been authorized from this reserve": [
+        ""
+      ],
+      "Authorized": [
+        ""
+      ],
+      "Expiration": [
+        ""
+      ],
+      "amount of tip": [
+        ""
+      ],
+      "Justification": [
+        ""
+      ],
+      "reason for the tip": [
+        ""
+      ],
+      "URL after tip": [
+        ""
+      ],
+      "URL to visit after tip payment": [
+        ""
+      ],
+      "Reserves not yet funded": [
+        ""
+      ],
+      "Reserves ready": [
+        ""
+      ],
+      "add new reserve": [
+        ""
+      ],
+      "Expires at": [
+        ""
+      ],
+      "Initial": [
+        ""
+      ],
+      "delete selected reserve from the database": [
+        ""
+      ],
+      "authorize new tip from selected reserve": [
+        ""
+      ],
+      "There is no ready reserves yet, add more pressing the + sign or fund 
them": [
+        ""
+      ],
+      "Expected Balance": [
+        ""
+      ],
+      "could not create the tip": [
+        ""
+      ],
+      "should not be empty": [
+        ""
+      ],
+      "should be greater that 0": [
+        ""
+      ],
+      "can't be empty": [
+        ""
+      ],
+      "to short": [
+        ""
+      ],
+      "just letters and numbers from 2 to 7": [
+        ""
+      ],
+      "size of the key should be 32": [
+        ""
+      ],
+      "Identifier": [
+        ""
+      ],
+      "Name of the template in URLs.": [
+        ""
+      ],
+      "Describe what this template stands for": [
+        ""
+      ],
+      "Fixed summary": [
+        ""
+      ],
+      "If specified, this template will create order with the same summary": [
+        ""
+      ],
+      "Fixed price": [
+        ""
+      ],
+      "If specified, this template will create order with the same price": [
+        ""
+      ],
+      "Minimum age": [
+        ""
+      ],
+      "Is this contract restricted to some age?": [
+        ""
+      ],
+      "Payment timeout": [
+        ""
+      ],
+      "How much time has the customer to complete the payment once the order 
was created.": [
+        ""
+      ],
+      "Verification algorithm": [
+        ""
+      ],
+      "Algorithm to use to verify transaction in offline mode": [
+        ""
+      ],
+      "Point-of-sale key": [
+        ""
+      ],
+      "Useful to validate the purchase": [
+        ""
+      ],
+      "generate random secret key": [
+        ""
+      ],
+      "random": [
+        ""
+      ],
+      "show secret key": [
+        ""
+      ],
+      "hide secret key": [
+        ""
+      ],
+      "hide": [
+        ""
+      ],
+      "show": [
+        ""
+      ],
+      "could not inform template": [
+        ""
+      ],
+      "Amount is required": [
+        ""
+      ],
+      "Order summary is required": [
+        ""
+      ],
+      "New order for template": [
+        ""
+      ],
+      "Amount of the order": [
+        ""
+      ],
+      "Order summary": [
+        ""
+      ],
+      "could not create order from template": [
+        ""
+      ],
+      "Here you can specify a default value for fields that are not fixed. 
Default values can be edited by the customer before the payment.": [
+        ""
+      ],
+      "Fixed amount": [
+        ""
+      ],
+      "Default amount": [
+        ""
+      ],
+      "Default summary": [
+        ""
+      ],
+      "Print": [
+        ""
+      ],
+      "Setup TOTP": [
+        ""
+      ],
+      "Templates": [
+        ""
+      ],
+      "add new templates": [
+        ""
+      ],
+      "load more templates before the first one": [
+        ""
+      ],
+      "load newer templates": [
+        ""
+      ],
+      "delete selected templates from the database": [
+        ""
+      ],
+      "use template to create new order": [
+        ""
+      ],
+      "create qr code for the template": [
+        ""
+      ],
+      "load more templates after the last one": [
+        ""
+      ],
+      "load older templates": [
+        ""
+      ],
+      "There is no templates yet, add more pressing the + sign": [
+        ""
+      ],
+      "template delete successfully": [
+        ""
+      ],
+      "could not delete the template": [
+        ""
+      ],
+      "could not update template": [
+        ""
+      ],
+      "should be one of '%1$s'": [
+        ""
+      ],
+      "Webhook ID to use": [
+        ""
+      ],
+      "Event": [
+        ""
+      ],
+      "The event of the webhook: why the webhook is used": [
+        ""
+      ],
+      "Method": [
+        ""
+      ],
+      "Method used by the webhook": [
+        ""
+      ],
+      "URL": [
+        ""
+      ],
+      "URL of the webhook where the customer will be redirected": [
+        ""
+      ],
+      "Header": [
+        ""
+      ],
+      "Header template of the webhook": [
+        ""
+      ],
+      "Body": [
+        ""
+      ],
+      "Body template by the webhook": [
+        ""
+      ],
+      "Webhooks": [
+        ""
+      ],
+      "add new webhooks": [
+        ""
+      ],
+      "load more webhooks before the first one": [
+        ""
+      ],
+      "load newer webhooks": [
+        ""
+      ],
+      "Event type": [
+        ""
+      ],
+      "delete selected webhook from the database": [
+        ""
+      ],
+      "load more webhooks after the last one": [
+        ""
+      ],
+      "load older webhooks": [
+        ""
+      ],
+      "There is no webhooks yet, add more pressing the + sign": [
+        ""
+      ],
+      "webhook delete successfully": [
+        ""
+      ],
+      "could not delete the webhook": [
+        ""
+      ],
+      "check the id, does not look valid": [
+        ""
+      ],
+      "should have 52 characters, current %1$s": [
+        ""
+      ],
+      "URL doesn't have the right format": [
+        ""
+      ],
+      "Credited bank account": [
+        ""
+      ],
+      "Select one account": [
+        ""
+      ],
+      "Bank account of the merchant where the payment was received": [
+        ""
+      ],
+      "Wire transfer ID": [
+        ""
+      ],
+      "unique identifier of the wire transfer used by the exchange, must be 52 
characters long": [
+        ""
+      ],
+      "Base URL of the exchange that made the transfer, should have been in 
the wire transfer subject": [
+        ""
+      ],
+      "Amount credited": [
+        ""
+      ],
+      "Actual amount that was wired to the merchant's bank account": [
+        ""
+      ],
+      "could not inform transfer": [
+        ""
+      ],
+      "Transfers": [
+        ""
+      ],
+      "add new transfer": [
+        ""
+      ],
+      "load more transfers before the first one": [
+        ""
+      ],
+      "load newer transfers": [
+        ""
+      ],
+      "Credit": [
+        ""
+      ],
+      "Confirmed": [
+        ""
+      ],
+      "Verified": [
+        ""
+      ],
+      "Executed at": [
+        ""
+      ],
+      "yes": [
+        ""
+      ],
+      "no": [
+        ""
+      ],
+      "unknown": [
+        ""
+      ],
+      "delete selected transfer from the database": [
+        ""
+      ],
+      "load more transfer after the last one": [
+        ""
+      ],
+      "load older transfers": [
+        ""
+      ],
+      "There is no transfer yet, add more pressing the + sign": [
+        ""
+      ],
+      "filter by account address": [
+        ""
+      ],
+      "only show wire transfers confirmed by the merchant": [
+        ""
+      ],
+      "only show wire transfers claimed by the exchange": [
+        ""
+      ],
+      "Unverified": [
+        ""
+      ],
+      "is not valid": [
+        ""
+      ],
+      "is not a number": [
+        ""
+      ],
+      "must be 1 or greater": [
+        ""
+      ],
+      "max 7 lines": [
+        ""
+      ],
+      "change authorization configuration": [
+        ""
+      ],
+      "Need to complete marked fields and choose authorization method": [
+        ""
+      ],
+      "This is not a valid bitcoin address.": [
+        ""
+      ],
+      "This is not a valid Ethereum address.": [
+        ""
+      ],
+      "IBAN numbers usually have more that 4 digits": [
+        ""
+      ],
+      "IBAN numbers usually have less that 34 digits": [
+        ""
+      ],
+      "IBAN country code not found": [
+        ""
+      ],
+      "IBAN number is not valid, checksum is wrong": [
+        ""
+      ],
+      "Target type": [
+        ""
+      ],
+      "Method to use for wire transfer": [
+        ""
+      ],
+      "Routing": [
+        ""
+      ],
+      "Routing number.": [
+        ""
+      ],
+      "Account": [
+        ""
+      ],
+      "Account number.": [
+        ""
+      ],
+      "Business Identifier Code.": [
+        ""
+      ],
+      "Bank Account Number.": [
+        ""
+      ],
+      "Unified Payment Interface.": [
+        ""
+      ],
+      "Bitcoin protocol.": [
+        ""
+      ],
+      "Ethereum protocol.": [
+        ""
+      ],
+      "Interledger protocol.": [
+        ""
+      ],
+      "Host": [
+        ""
+      ],
+      "Bank host.": [
+        ""
+      ],
+      "Bank account.": [
+        ""
+      ],
+      "Bank account owner's name.": [
+        ""
+      ],
+      "No accounts yet.": [
+        ""
+      ],
+      "Name of the instance in URLs. The 'default' instance is special in that 
it is used to administer other instances.": [
+        ""
+      ],
+      "Business name": [
+        ""
+      ],
+      "Legal name of the business represented by this instance.": [
+        ""
+      ],
+      "Email": [
+        ""
+      ],
+      "Contact email": [
+        ""
+      ],
+      "Website URL": [
+        ""
+      ],
+      "URL.": [
+        ""
+      ],
+      "Logo": [
+        ""
+      ],
+      "Logo image.": [
+        ""
+      ],
+      "Bank account": [
+        ""
+      ],
+      "URI specifying bank account for crediting revenue.": [
+        ""
+      ],
+      "Default max deposit fee": [
+        ""
+      ],
+      "Maximum deposit fees this merchant is willing to pay per order by 
default.": [
+        ""
+      ],
+      "Default max wire fee": [
+        ""
+      ],
+      "Maximum wire fees this merchant is willing to pay per wire transfer by 
default.": [
+        ""
+      ],
+      "Default wire fee amortization": [
+        ""
+      ],
+      "Number of orders excess wire transfer fees will be divided by to 
compute per order surcharge.": [
+        ""
+      ],
+      "Physical location of the merchant.": [
+        ""
+      ],
+      "Jurisdiction": [
+        ""
+      ],
+      "Jurisdiction for legal disputes with the merchant.": [
+        ""
+      ],
+      "Default payment delay": [
+        ""
+      ],
+      "Time customers have to pay an order before the offer expires by 
default.": [
+        ""
+      ],
+      "Default wire transfer delay": [
+        ""
+      ],
+      "Maximum time an exchange is allowed to delay wiring funds to the 
merchant, enabling it to aggregate smaller payments into larger wire transfers 
and reducing wire fees.": [
+        ""
+      ],
+      "Instance id": [
+        ""
+      ],
+      "Change the authorization method use for this instance.": [
+        ""
+      ],
+      "Manage access token": [
+        ""
+      ],
+      "Failed to create instance": [
+        ""
+      ],
+      "Login required": [
+        ""
+      ],
+      "Please enter your access token.": [
+        ""
+      ],
+      "Access Token": [
+        ""
+      ],
+      "The request to the backend take too long and was cancelled": [
+        ""
+      ],
+      "Diagnostic from %1$s is \"%2$s\"": [
+        ""
+      ],
+      "The backend reported a problem: HTTP status #%1$s": [
+        ""
+      ],
+      "Diagnostic from %1$s is '%2$s'": [
+        ""
+      ],
+      "Access denied": [
+        ""
+      ],
+      "The access token provided is invalid.": [
+        ""
+      ],
+      "No 'default' instance configured yet.": [
+        ""
+      ],
+      "Create a 'default' instance to begin using the merchant backoffice.": [
+        ""
+      ],
+      "The access token provided is invalid": [
+        ""
+      ],
+      "Hide for today": [
+        ""
+      ],
+      "Instance": [
+        ""
+      ],
+      "Settings": [
+        ""
+      ],
+      "Connection": [
+        ""
+      ],
+      "New": [
+        ""
+      ],
+      "List": [
+        ""
+      ],
+      "Log out": [
+        ""
+      ],
+      "Check your token is valid": [
+        ""
+      ],
+      "Couldn't access the server.": [
+        ""
+      ],
+      "Could not infer instance id from url %1$s": [
+        ""
+      ],
+      "Server not found": [
+        ""
+      ],
+      "Server response with an error code": [
+        ""
+      ],
+      "Got message %1$s from %2$s": [
+        ""
+      ],
+      "Response from server is unreadable, http status: %1$s": [
+        ""
+      ],
+      "Unexpected Error": [
+        ""
+      ],
+      "The value %1$s is invalid for a payment url": [
+        ""
+      ],
+      "add element to the list": [
+        ""
+      ],
+      "add": [
+        ""
+      ],
+      "Deleting": [
+        ""
+      ],
+      "Changing": [
+        ""
+      ],
+      "Order ID": [
+        ""
+      ],
+      "Payment URL": [
+        ""
+      ]
+    }
+  }
+};
+
+strings['sv'] = {
+  "domain": "messages",
+  "locale_data": {
+    "messages": {
+      "": {
+        "domain": "messages",
+        "plural_forms": "nplurals=2; plural=(n != 1);",
+        "lang": ""
+      },
+      "Cancel": [
+        ""
+      ],
+      "%1$s": [
+        ""
+      ],
+      "Close": [
+        ""
+      ],
+      "Continue": [
+        ""
+      ],
+      "Clear": [
+        ""
+      ],
+      "Confirm": [
+        ""
+      ],
+      "is not the same as the current access token": [
+        ""
+      ],
+      "cannot be empty": [
+        ""
+      ],
+      "cannot be the same as the old token": [
+        ""
+      ],
+      "is not the same": [
+        ""
+      ],
+      "You are updating the access token from instance with id %1$s": [
+        ""
+      ],
+      "Old access token": [
+        ""
+      ],
+      "access token currently in use": [
+        ""
+      ],
+      "New access token": [
+        ""
+      ],
+      "next access token to be used": [
+        ""
+      ],
+      "Repeat access token": [
+        ""
+      ],
+      "confirm the same access token": [
+        ""
+      ],
+      "Clearing the access token will mean public access to the instance": [
+        ""
+      ],
+      "cannot be the same as the old access token": [
+        ""
+      ],
+      "You are setting the access token for the new instance": [
+        ""
+      ],
+      "With external authorization method no check will be done by the 
merchant backend": [
+        ""
+      ],
+      "Set external authorization": [
+        ""
+      ],
+      "Set access token": [
+        ""
+      ],
+      "Operation in progress...": [
+        ""
+      ],
+      "The operation will be automatically canceled after %1$s seconds": [
+        ""
+      ],
+      "Instances": [
+        ""
+      ],
+      "Delete": [
+        ""
+      ],
+      "add new instance": [
+        ""
+      ],
+      "ID": [
+        ""
+      ],
+      "Name": [
+        ""
+      ],
+      "Edit": [
+        ""
+      ],
+      "Purge": [
+        ""
+      ],
+      "There is no instances yet, add more pressing the + sign": [
+        ""
+      ],
+      "Only show active instances": [
+        ""
+      ],
+      "Active": [
+        ""
+      ],
+      "Only show deleted instances": [
+        ""
+      ],
+      "Deleted": [
+        ""
+      ],
+      "Show all instances": [
+        ""
+      ],
+      "All": [
+        ""
+      ],
+      "Instance \"%1$s\" (ID: %2$s) has been deleted": [
+        ""
+      ],
+      "Failed to delete instance": [
+        ""
+      ],
+      "Instance '%1$s' (ID: %2$s) has been disabled": [
+        ""
+      ],
+      "Failed to purge instance": [
+        ""
+      ],
+      "Pending KYC verification": [
+        ""
+      ],
+      "Timed out": [
+        ""
+      ],
+      "Exchange": [
+        ""
+      ],
+      "Target account": [
+        ""
+      ],
+      "KYC URL": [
+        ""
+      ],
+      "Code": [
+        ""
+      ],
+      "Http Status": [
+        ""
+      ],
+      "No pending kyc verification!": [
+        ""
+      ],
+      "change value to unknown date": [
+        ""
+      ],
+      "change value to empty": [
+        ""
+      ],
+      "clear": [
+        ""
+      ],
+      "change value to never": [
+        ""
+      ],
+      "never": [
+        ""
+      ],
+      "Country": [
+        ""
+      ],
+      "Address": [
+        ""
+      ],
+      "Building number": [
+        ""
+      ],
+      "Building name": [
+        ""
+      ],
+      "Street": [
+        ""
+      ],
+      "Post code": [
+        ""
+      ],
+      "Town location": [
+        ""
+      ],
+      "Town": [
+        ""
+      ],
+      "District": [
+        ""
+      ],
+      "Country subdivision": [
+        ""
+      ],
+      "Product id": [
+        ""
+      ],
+      "Description": [
+        ""
+      ],
+      "Product": [
+        ""
+      ],
+      "search products by it's description or id": [
+        ""
+      ],
+      "no products found with that description": [
+        ""
+      ],
+      "You must enter a valid product identifier.": [
+        ""
+      ],
+      "Quantity must be greater than 0!": [
+        ""
+      ],
+      "This quantity exceeds remaining stock. Currently, only %1$s units 
remain unreserved in stock.": [
+        ""
+      ],
+      "Quantity": [
+        ""
+      ],
+      "how many products will be added": [
+        ""
+      ],
+      "Add from inventory": [
+        ""
+      ],
+      "Image should be smaller than 1 MB": [
+        ""
+      ],
+      "Add": [
+        ""
+      ],
+      "Remove": [
+        ""
+      ],
+      "No taxes configured for this product.": [
+        ""
+      ],
+      "Amount": [
+        ""
+      ],
+      "Taxes can be in currencies that differ from the main currency used by 
the merchant.": [
+        ""
+      ],
+      "Enter currency and value separated with a colon, e.g. 
&quot;USD:2.3&quot;.": [
+        ""
+      ],
+      "Legal name of the tax, e.g. VAT or import duties.": [
+        ""
+      ],
+      "add tax to the tax list": [
+        ""
+      ],
+      "describe and add a product that is not in the inventory list": [
+        ""
+      ],
+      "Add custom product": [
+        ""
+      ],
+      "Complete information of the product": [
+        ""
+      ],
+      "Image": [
+        ""
+      ],
+      "photo of the product": [
+        ""
+      ],
+      "full product description": [
+        ""
+      ],
+      "Unit": [
+        ""
+      ],
+      "name of the product unit": [
+        ""
+      ],
+      "Price": [
+        ""
+      ],
+      "amount in the current currency": [
+        ""
+      ],
+      "Taxes": [
+        ""
+      ],
+      "image": [
+        ""
+      ],
+      "description": [
+        ""
+      ],
+      "quantity": [
+        ""
+      ],
+      "unit price": [
+        ""
+      ],
+      "total price": [
+        ""
+      ],
+      "required": [
+        ""
+      ],
+      "not valid": [
+        ""
+      ],
+      "must be greater than 0": [
+        ""
+      ],
+      "not a valid json": [
+        ""
+      ],
+      "should be in the future": [
+        ""
+      ],
+      "refund deadline cannot be before pay deadline": [
+        ""
+      ],
+      "wire transfer deadline cannot be before refund deadline": [
+        ""
+      ],
+      "wire transfer deadline cannot be before pay deadline": [
+        ""
+      ],
+      "should have a refund deadline": [
+        ""
+      ],
+      "auto refund cannot be after refund deadline": [
+        ""
+      ],
+      "Manage products in order": [
+        ""
+      ],
+      "Manage list of products in the order.": [
+        ""
+      ],
+      "Remove this product from the order.": [
+        ""
+      ],
+      "Total price": [
+        ""
+      ],
+      "total product price added up": [
+        ""
+      ],
+      "Amount to be paid by the customer": [
+        ""
+      ],
+      "Order price": [
+        ""
+      ],
+      "final order price": [
+        ""
+      ],
+      "Summary": [
+        ""
+      ],
+      "Title of the order to be shown to the customer": [
+        ""
+      ],
+      "Shipping and Fulfillment": [
+        ""
+      ],
+      "Delivery date": [
+        ""
+      ],
+      "Deadline for physical delivery assured by the merchant.": [
+        ""
+      ],
+      "Location": [
+        ""
+      ],
+      "address where the products will be delivered": [
+        ""
+      ],
+      "Fulfillment URL": [
+        ""
+      ],
+      "URL to which the user will be redirected after successful payment.": [
+        ""
+      ],
+      "Taler payment options": [
+        ""
+      ],
+      "Override default Taler payment settings for this order": [
+        ""
+      ],
+      "Payment deadline": [
+        ""
+      ],
+      "Deadline for the customer to pay for the offer before it expires. 
Inventory products will be reserved until this deadline.": [
+        ""
+      ],
+      "Refund deadline": [
+        ""
+      ],
+      "Time until which the order can be refunded by the merchant.": [
+        ""
+      ],
+      "Wire transfer deadline": [
+        ""
+      ],
+      "Deadline for the exchange to make the wire transfer.": [
+        ""
+      ],
+      "Auto-refund deadline": [
+        ""
+      ],
+      "Time until which the wallet will automatically check for refunds 
without user interaction.": [
+        ""
+      ],
+      "Maximum deposit fee": [
+        ""
+      ],
+      "Maximum deposit fees the merchant is willing to cover for this order. 
Higher deposit fees must be covered in full by the consumer.": [
+        ""
+      ],
+      "Maximum wire fee": [
+        ""
+      ],
+      "Maximum aggregate wire fees the merchant is willing to cover for this 
order. Wire fees exceeding this amount are to be covered by the customers.": [
+        ""
+      ],
+      "Wire fee amortization": [
+        ""
+      ],
+      "Factor by which wire fees exceeding the above threshold are divided to 
determine the share of excess wire fees to be paid explicitly by the 
consumer.": [
+        ""
+      ],
+      "Create token": [
+        ""
+      ],
+      "Uncheck this option if the merchant backend generated an order ID with 
enough entropy to prevent adversarial claims.": [
+        ""
+      ],
+      "Minimum age required": [
+        ""
+      ],
+      "Any value greater than 0 will limit the coins able be used to pay this 
contract. If empty the age restriction will be defined by the products": [
+        ""
+      ],
+      "Min age defined by the producs is %1$s": [
+        ""
+      ],
+      "Additional information": [
+        ""
+      ],
+      "Custom information to be included in the contract for this order.": [
+        ""
+      ],
+      "You must enter a value in JavaScript Object Notation (JSON).": [
+        ""
+      ],
+      "days": [
+        ""
+      ],
+      "hours": [
+        ""
+      ],
+      "minutes": [
+        ""
+      ],
+      "seconds": [
+        ""
+      ],
+      "forever": [
+        ""
+      ],
+      "%1$sM": [
+        ""
+      ],
+      "%1$sY": [
+        ""
+      ],
+      "%1$sd": [
+        ""
+      ],
+      "%1$sh": [
+        ""
+      ],
+      "%1$smin": [
+        ""
+      ],
+      "%1$ssec": [
+        ""
+      ],
+      "Orders": [
+        ""
+      ],
+      "create order": [
+        ""
+      ],
+      "load newer orders": [
+        ""
+      ],
+      "Date": [
+        ""
+      ],
+      "Refund": [
+        ""
+      ],
+      "copy url": [
+        ""
+      ],
+      "load older orders": [
+        ""
+      ],
+      "No orders have been found matching your query!": [
+        ""
+      ],
+      "duplicated": [
+        ""
+      ],
+      "invalid format": [
+        ""
+      ],
+      "this value exceed the refundable amount": [
+        ""
+      ],
+      "date": [
+        ""
+      ],
+      "amount": [
+        ""
+      ],
+      "reason": [
+        ""
+      ],
+      "amount to be refunded": [
+        ""
+      ],
+      "Max refundable:": [
+        ""
+      ],
+      "Reason": [
+        ""
+      ],
+      "Choose one...": [
+        ""
+      ],
+      "requested by the customer": [
+        ""
+      ],
+      "other": [
+        ""
+      ],
+      "why this order is being refunded": [
+        ""
+      ],
+      "more information to give context": [
+        ""
+      ],
+      "Contract Terms": [
+        ""
+      ],
+      "human-readable description of the whole purchase": [
+        ""
+      ],
+      "total price for the transaction": [
+        ""
+      ],
+      "URL for this purchase": [
+        ""
+      ],
+      "Max fee": [
+        ""
+      ],
+      "maximum total deposit fee accepted by the merchant for this contract": [
+        ""
+      ],
+      "Max wire fee": [
+        ""
+      ],
+      "maximum wire fee accepted by the merchant": [
+        ""
+      ],
+      "over how many customer transactions does the merchant expect to 
amortize wire fees on average": [
+        ""
+      ],
+      "Created at": [
+        ""
+      ],
+      "time when this contract was generated": [
+        ""
+      ],
+      "after this deadline has passed no refunds will be accepted": [
+        ""
+      ],
+      "after this deadline, the merchant won't accept payments for the 
contract": [
+        ""
+      ],
+      "transfer deadline for the exchange": [
+        ""
+      ],
+      "time indicating when the order should be delivered": [
+        ""
+      ],
+      "where the order will be delivered": [
+        ""
+      ],
+      "Auto-refund delay": [
+        ""
+      ],
+      "how long the wallet should try to get an automatic refund for the 
purchase": [
+        ""
+      ],
+      "Extra info": [
+        ""
+      ],
+      "extra data that is only interpreted by the merchant frontend": [
+        ""
+      ],
+      "Order": [
+        ""
+      ],
+      "claimed": [
+        ""
+      ],
+      "claimed at": [
+        ""
+      ],
+      "Timeline": [
+        ""
+      ],
+      "Payment details": [
+        ""
+      ],
+      "Order status": [
+        ""
+      ],
+      "Product list": [
+        ""
+      ],
+      "paid": [
+        ""
+      ],
+      "wired": [
+        ""
+      ],
+      "refunded": [
+        ""
+      ],
+      "refund order": [
+        ""
+      ],
+      "not refundable": [
+        ""
+      ],
+      "refund": [
+        ""
+      ],
+      "Refunded amount": [
+        ""
+      ],
+      "Refund taken": [
+        ""
+      ],
+      "Status URL": [
+        ""
+      ],
+      "Refund URI": [
+        ""
+      ],
+      "unpaid": [
+        ""
+      ],
+      "pay at": [
+        ""
+      ],
+      "created at": [
+        ""
+      ],
+      "Order status URL": [
+        ""
+      ],
+      "Payment URI": [
+        ""
+      ],
+      "Unknown order status. This is an error, please contact the 
administrator.": [
+        ""
+      ],
+      "Back": [
+        ""
+      ],
+      "refund created successfully": [
+        ""
+      ],
+      "could not create the refund": [
+        ""
+      ],
+      "select date to show nearby orders": [
+        ""
+      ],
+      "order id": [
+        ""
+      ],
+      "jump to order with the given order ID": [
+        ""
+      ],
+      "remove all filters": [
+        ""
+      ],
+      "only show paid orders": [
+        ""
+      ],
+      "Paid": [
+        ""
+      ],
+      "only show orders with refunds": [
+        ""
+      ],
+      "Refunded": [
+        ""
+      ],
+      "only show orders where customers paid, but wire payments from payment 
provider are still pending": [
+        ""
+      ],
+      "Not wired": [
+        ""
+      ],
+      "clear date filter": [
+        ""
+      ],
+      "date (YYYY/MM/DD)": [
+        ""
+      ],
+      "Enter an order id": [
+        ""
+      ],
+      "order not found": [
+        ""
+      ],
+      "could not get the order to refund": [
+        ""
+      ],
+      "Loading...": [
+        ""
+      ],
+      "click here to configure the stock of the product, leave it as is and 
the backend will not control stock": [
+        ""
+      ],
+      "Manage stock": [
+        ""
+      ],
+      "this product has been configured without stock control": [
+        ""
+      ],
+      "Infinite": [
+        ""
+      ],
+      "lost cannot be greater than current and incoming (max %1$s)": [
+        ""
+      ],
+      "Incoming": [
+        ""
+      ],
+      "Lost": [
+        ""
+      ],
+      "Current": [
+        ""
+      ],
+      "remove stock control for this product": [
+        ""
+      ],
+      "without stock": [
+        ""
+      ],
+      "Next restock": [
+        ""
+      ],
+      "Delivery address": [
+        ""
+      ],
+      "product identification to use in URLs (for internal use only)": [
+        ""
+      ],
+      "illustration of the product for customers": [
+        ""
+      ],
+      "product description for customers": [
+        ""
+      ],
+      "Age restricted": [
+        ""
+      ],
+      "is this product restricted for customer below certain age?": [
+        ""
+      ],
+      "unit describing quantity of product sold (e.g. 2 kilograms, 5 liters, 3 
items, 5 meters) for customers": [
+        ""
+      ],
+      "sale price for customers, including taxes, for above units of the 
product": [
+        ""
+      ],
+      "Stock": [
+        ""
+      ],
+      "product inventory for products with finite supply (for internal use 
only)": [
+        ""
+      ],
+      "taxes included in the product price, exposed to customers": [
+        ""
+      ],
+      "Need to complete marked fields": [
+        ""
+      ],
+      "could not create product": [
+        ""
+      ],
+      "Products": [
+        ""
+      ],
+      "add product to inventory": [
+        ""
+      ],
+      "Sell": [
+        ""
+      ],
+      "Profit": [
+        ""
+      ],
+      "Sold": [
+        ""
+      ],
+      "free": [
+        ""
+      ],
+      "go to product update page": [
+        ""
+      ],
+      "Update": [
+        ""
+      ],
+      "remove this product from the database": [
+        ""
+      ],
+      "update the product with new price": [
+        ""
+      ],
+      "update product with new price": [
+        ""
+      ],
+      "add more elements to the inventory": [
+        ""
+      ],
+      "report elements lost in the inventory": [
+        ""
+      ],
+      "new price for the product": [
+        ""
+      ],
+      "the are value with errors": [
+        ""
+      ],
+      "update product with new stock and price": [
+        ""
+      ],
+      "There is no products yet, add more pressing the + sign": [
+        ""
+      ],
+      "product updated successfully": [
+        ""
+      ],
+      "could not update the product": [
+        ""
+      ],
+      "product delete successfully": [
+        ""
+      ],
+      "could not delete the product": [
+        ""
+      ],
+      "Product id:": [
+        ""
+      ],
+      "To complete the setup of the reserve, you must now initiate a wire 
transfer using the given wire transfer subject and crediting the specified 
amount to the indicated account of the exchange.": [
+        ""
+      ],
+      "If your system supports RFC 8905, you can do this by opening this 
URI:": [
+        ""
+      ],
+      "it should be greater than 0": [
+        ""
+      ],
+      "must be a valid URL": [
+        ""
+      ],
+      "Initial balance": [
+        ""
+      ],
+      "balance prior to deposit": [
+        ""
+      ],
+      "Exchange URL": [
+        ""
+      ],
+      "URL of exchange": [
+        ""
+      ],
+      "Next": [
+        ""
+      ],
+      "Wire method": [
+        ""
+      ],
+      "method to use for wire transfer": [
+        ""
+      ],
+      "Select one wire method": [
+        ""
+      ],
+      "could not create reserve": [
+        ""
+      ],
+      "Valid until": [
+        ""
+      ],
+      "Created balance": [
+        ""
+      ],
+      "Exchange balance": [
+        ""
+      ],
+      "Picked up": [
+        ""
+      ],
+      "Committed": [
+        ""
+      ],
+      "Account address": [
+        ""
+      ],
+      "Subject": [
+        ""
+      ],
+      "Tips": [
+        ""
+      ],
+      "No tips has been authorized from this reserve": [
+        ""
+      ],
+      "Authorized": [
+        ""
+      ],
+      "Expiration": [
+        ""
+      ],
+      "amount of tip": [
+        ""
+      ],
+      "Justification": [
+        ""
+      ],
+      "reason for the tip": [
+        ""
+      ],
+      "URL after tip": [
+        ""
+      ],
+      "URL to visit after tip payment": [
+        ""
+      ],
+      "Reserves not yet funded": [
+        ""
+      ],
+      "Reserves ready": [
+        ""
+      ],
+      "add new reserve": [
+        ""
+      ],
+      "Expires at": [
+        ""
+      ],
+      "Initial": [
+        ""
+      ],
+      "delete selected reserve from the database": [
+        ""
+      ],
+      "authorize new tip from selected reserve": [
+        ""
+      ],
+      "There is no ready reserves yet, add more pressing the + sign or fund 
them": [
+        ""
+      ],
+      "Expected Balance": [
+        ""
+      ],
+      "could not create the tip": [
+        ""
+      ],
+      "should not be empty": [
+        ""
+      ],
+      "should be greater that 0": [
+        ""
+      ],
+      "can't be empty": [
+        ""
+      ],
+      "to short": [
+        ""
+      ],
+      "just letters and numbers from 2 to 7": [
+        ""
+      ],
+      "size of the key should be 32": [
+        ""
+      ],
+      "Identifier": [
+        ""
+      ],
+      "Name of the template in URLs.": [
+        ""
+      ],
+      "Describe what this template stands for": [
+        ""
+      ],
+      "Fixed summary": [
+        ""
+      ],
+      "If specified, this template will create order with the same summary": [
+        ""
+      ],
+      "Fixed price": [
+        ""
+      ],
+      "If specified, this template will create order with the same price": [
+        ""
+      ],
+      "Minimum age": [
+        ""
+      ],
+      "Is this contract restricted to some age?": [
+        ""
+      ],
+      "Payment timeout": [
+        ""
+      ],
+      "How much time has the customer to complete the payment once the order 
was created.": [
+        ""
+      ],
+      "Verification algorithm": [
+        ""
+      ],
+      "Algorithm to use to verify transaction in offline mode": [
+        ""
+      ],
+      "Point-of-sale key": [
+        ""
+      ],
+      "Useful to validate the purchase": [
+        ""
+      ],
+      "generate random secret key": [
+        ""
+      ],
+      "random": [
+        ""
+      ],
+      "show secret key": [
+        ""
+      ],
+      "hide secret key": [
+        ""
+      ],
+      "hide": [
+        ""
+      ],
+      "show": [
+        ""
+      ],
+      "could not inform template": [
+        ""
+      ],
+      "Amount is required": [
+        ""
+      ],
+      "Order summary is required": [
+        ""
+      ],
+      "New order for template": [
+        ""
+      ],
+      "Amount of the order": [
+        ""
+      ],
+      "Order summary": [
+        ""
+      ],
+      "could not create order from template": [
+        ""
+      ],
+      "Here you can specify a default value for fields that are not fixed. 
Default values can be edited by the customer before the payment.": [
+        ""
+      ],
+      "Fixed amount": [
+        ""
+      ],
+      "Default amount": [
+        ""
+      ],
+      "Default summary": [
+        ""
+      ],
+      "Print": [
+        ""
+      ],
+      "Setup TOTP": [
+        ""
+      ],
+      "Templates": [
+        ""
+      ],
+      "add new templates": [
+        ""
+      ],
+      "load more templates before the first one": [
+        ""
+      ],
+      "load newer templates": [
+        ""
+      ],
+      "delete selected templates from the database": [
+        ""
+      ],
+      "use template to create new order": [
+        ""
+      ],
+      "create qr code for the template": [
+        ""
+      ],
+      "load more templates after the last one": [
+        ""
+      ],
+      "load older templates": [
+        ""
+      ],
+      "There is no templates yet, add more pressing the + sign": [
+        ""
+      ],
+      "template delete successfully": [
+        ""
+      ],
+      "could not delete the template": [
+        ""
+      ],
+      "could not update template": [
+        ""
+      ],
+      "should be one of '%1$s'": [
+        ""
+      ],
+      "Webhook ID to use": [
+        ""
+      ],
+      "Event": [
+        ""
+      ],
+      "The event of the webhook: why the webhook is used": [
+        ""
+      ],
+      "Method": [
+        ""
+      ],
+      "Method used by the webhook": [
+        ""
+      ],
+      "URL": [
+        ""
+      ],
+      "URL of the webhook where the customer will be redirected": [
+        ""
+      ],
+      "Header": [
+        ""
+      ],
+      "Header template of the webhook": [
+        ""
+      ],
+      "Body": [
+        ""
+      ],
+      "Body template by the webhook": [
+        ""
+      ],
+      "Webhooks": [
+        ""
+      ],
+      "add new webhooks": [
+        ""
+      ],
+      "load more webhooks before the first one": [
+        ""
+      ],
+      "load newer webhooks": [
+        ""
+      ],
+      "Event type": [
+        ""
+      ],
+      "delete selected webhook from the database": [
+        ""
+      ],
+      "load more webhooks after the last one": [
+        ""
+      ],
+      "load older webhooks": [
+        ""
+      ],
+      "There is no webhooks yet, add more pressing the + sign": [
+        ""
+      ],
+      "webhook delete successfully": [
+        ""
+      ],
+      "could not delete the webhook": [
+        ""
+      ],
+      "check the id, does not look valid": [
+        ""
+      ],
+      "should have 52 characters, current %1$s": [
+        ""
+      ],
+      "URL doesn't have the right format": [
+        ""
+      ],
+      "Credited bank account": [
+        ""
+      ],
+      "Select one account": [
+        ""
+      ],
+      "Bank account of the merchant where the payment was received": [
+        ""
+      ],
+      "Wire transfer ID": [
+        ""
+      ],
+      "unique identifier of the wire transfer used by the exchange, must be 52 
characters long": [
+        ""
+      ],
+      "Base URL of the exchange that made the transfer, should have been in 
the wire transfer subject": [
+        ""
+      ],
+      "Amount credited": [
+        ""
+      ],
+      "Actual amount that was wired to the merchant's bank account": [
+        ""
+      ],
+      "could not inform transfer": [
+        ""
+      ],
+      "Transfers": [
+        ""
+      ],
+      "add new transfer": [
+        ""
+      ],
+      "load more transfers before the first one": [
+        ""
+      ],
+      "load newer transfers": [
+        ""
+      ],
+      "Credit": [
+        ""
+      ],
+      "Confirmed": [
+        ""
+      ],
+      "Verified": [
+        ""
+      ],
+      "Executed at": [
+        ""
+      ],
+      "yes": [
+        ""
+      ],
+      "no": [
+        ""
+      ],
+      "unknown": [
+        ""
+      ],
+      "delete selected transfer from the database": [
+        ""
+      ],
+      "load more transfer after the last one": [
+        ""
+      ],
+      "load older transfers": [
+        ""
+      ],
+      "There is no transfer yet, add more pressing the + sign": [
+        ""
+      ],
+      "filter by account address": [
+        ""
+      ],
+      "only show wire transfers confirmed by the merchant": [
+        ""
+      ],
+      "only show wire transfers claimed by the exchange": [
+        ""
+      ],
+      "Unverified": [
+        ""
+      ],
+      "is not valid": [
+        ""
+      ],
+      "is not a number": [
+        ""
+      ],
+      "must be 1 or greater": [
+        ""
+      ],
+      "max 7 lines": [
+        ""
+      ],
+      "change authorization configuration": [
+        ""
+      ],
+      "Need to complete marked fields and choose authorization method": [
+        ""
+      ],
+      "This is not a valid bitcoin address.": [
+        ""
+      ],
+      "This is not a valid Ethereum address.": [
+        ""
+      ],
+      "IBAN numbers usually have more that 4 digits": [
+        ""
+      ],
+      "IBAN numbers usually have less that 34 digits": [
+        ""
+      ],
+      "IBAN country code not found": [
+        ""
+      ],
+      "IBAN number is not valid, checksum is wrong": [
+        ""
+      ],
+      "Target type": [
+        ""
+      ],
+      "Method to use for wire transfer": [
+        ""
+      ],
+      "Routing": [
+        ""
+      ],
+      "Routing number.": [
+        ""
+      ],
+      "Account": [
+        ""
+      ],
+      "Account number.": [
+        ""
+      ],
+      "Business Identifier Code.": [
+        ""
+      ],
+      "Bank Account Number.": [
+        ""
+      ],
+      "Unified Payment Interface.": [
+        ""
+      ],
+      "Bitcoin protocol.": [
+        ""
+      ],
+      "Ethereum protocol.": [
+        ""
+      ],
+      "Interledger protocol.": [
+        ""
+      ],
+      "Host": [
+        ""
+      ],
+      "Bank host.": [
+        ""
+      ],
+      "Bank account.": [
+        ""
+      ],
+      "Bank account owner's name.": [
+        ""
+      ],
+      "No accounts yet.": [
+        ""
+      ],
+      "Name of the instance in URLs. The 'default' instance is special in that 
it is used to administer other instances.": [
+        ""
+      ],
+      "Business name": [
+        ""
+      ],
+      "Legal name of the business represented by this instance.": [
+        ""
+      ],
+      "Email": [
+        ""
+      ],
+      "Contact email": [
+        ""
+      ],
+      "Website URL": [
+        ""
+      ],
+      "URL.": [
+        ""
+      ],
+      "Logo": [
+        ""
+      ],
+      "Logo image.": [
+        ""
+      ],
+      "Bank account": [
+        ""
+      ],
+      "URI specifying bank account for crediting revenue.": [
+        ""
+      ],
+      "Default max deposit fee": [
+        ""
+      ],
+      "Maximum deposit fees this merchant is willing to pay per order by 
default.": [
+        ""
+      ],
+      "Default max wire fee": [
+        ""
+      ],
+      "Maximum wire fees this merchant is willing to pay per wire transfer by 
default.": [
+        ""
+      ],
+      "Default wire fee amortization": [
+        ""
+      ],
+      "Number of orders excess wire transfer fees will be divided by to 
compute per order surcharge.": [
+        ""
+      ],
+      "Physical location of the merchant.": [
+        ""
+      ],
+      "Jurisdiction": [
+        ""
+      ],
+      "Jurisdiction for legal disputes with the merchant.": [
+        ""
+      ],
+      "Default payment delay": [
+        ""
+      ],
+      "Time customers have to pay an order before the offer expires by 
default.": [
+        ""
+      ],
+      "Default wire transfer delay": [
+        ""
+      ],
+      "Maximum time an exchange is allowed to delay wiring funds to the 
merchant, enabling it to aggregate smaller payments into larger wire transfers 
and reducing wire fees.": [
+        ""
+      ],
+      "Instance id": [
+        ""
+      ],
+      "Change the authorization method use for this instance.": [
+        ""
+      ],
+      "Manage access token": [
+        ""
+      ],
+      "Failed to create instance": [
+        ""
+      ],
+      "Login required": [
+        ""
+      ],
+      "Please enter your access token.": [
+        ""
+      ],
+      "Access Token": [
+        ""
+      ],
+      "The request to the backend take too long and was cancelled": [
+        ""
+      ],
+      "Diagnostic from %1$s is \"%2$s\"": [
+        ""
+      ],
+      "The backend reported a problem: HTTP status #%1$s": [
+        ""
+      ],
+      "Diagnostic from %1$s is '%2$s'": [
+        ""
+      ],
+      "Access denied": [
+        ""
+      ],
+      "The access token provided is invalid.": [
+        ""
+      ],
+      "No 'default' instance configured yet.": [
+        ""
+      ],
+      "Create a 'default' instance to begin using the merchant backoffice.": [
+        ""
+      ],
+      "The access token provided is invalid": [
+        ""
+      ],
+      "Hide for today": [
+        ""
+      ],
+      "Instance": [
+        ""
+      ],
+      "Settings": [
+        ""
+      ],
+      "Connection": [
+        ""
+      ],
+      "New": [
+        ""
+      ],
+      "List": [
+        ""
+      ],
+      "Log out": [
+        ""
+      ],
+      "Check your token is valid": [
+        ""
+      ],
+      "Couldn't access the server.": [
+        ""
+      ],
+      "Could not infer instance id from url %1$s": [
+        ""
+      ],
+      "Server not found": [
+        ""
+      ],
+      "Server response with an error code": [
+        ""
+      ],
+      "Got message %1$s from %2$s": [
+        ""
+      ],
+      "Response from server is unreadable, http status: %1$s": [
+        ""
+      ],
+      "Unexpected Error": [
+        ""
+      ],
+      "The value %1$s is invalid for a payment url": [
+        ""
+      ],
+      "add element to the list": [
+        ""
+      ],
+      "add": [
+        ""
+      ],
+      "Deleting": [
+        ""
+      ],
+      "Changing": [
+        ""
+      ],
+      "Order ID": [
+        ""
+      ],
+      "Payment URL": [
+        ""
+      ]
+    }
+  }
+};
+
diff --git a/packages/auditor-backoffice-ui/src/i18n/sv.po 
b/packages/auditor-backoffice-ui/src/i18n/sv.po
new file mode 100644
index 000000000..d8d0bae29
--- /dev/null
+++ b/packages/auditor-backoffice-ui/src/i18n/sv.po
@@ -0,0 +1,2741 @@
+# This file is part of TALER
+# (C) 2016 GNUnet e.V.
+#
+# TALER is free software; you can redistribute it and/or modify it under the
+# terms of the GNU General Public License as published by the Free Software
+# Foundation; either version 3, or (at your option) any later version.
+#
+# TALER is distributed in the hope that it will be useful, but WITHOUT ANY
+# WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
+# A PARTICULAR PURPOSE.  See the GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License along with
+# TALER; see the file COPYING.  If not, see <http://www.gnu.org/licenses/>
+#
+#, fuzzy
+msgid ""
+msgstr ""
+"Project-Id-Version: Taler Wallet\n"
+"Report-Msgid-Bugs-To: taler@gnu.org\n"
+"POT-Creation-Date: 2016-11-23 00:00+0100\n"
+"PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n"
+"Last-Translator: FULL NAME <EMAIL@ADDRESS>\n"
+"Language-Team: LANGUAGE <LL@li.org>\n"
+"Language: \n"
+"MIME-Version: 1.0\n"
+"Content-Type: text/plain; charset=UTF-8\n"
+"Content-Transfer-Encoding: 8bit\n"
+"Plural-Forms: nplurals=2; plural=(n != 1);\n"
+
+#: src/components/modal/index.tsx:71
+#, c-format
+msgid "Cancel"
+msgstr ""
+
+#: src/components/modal/index.tsx:79
+#, c-format
+msgid "%1$s"
+msgstr ""
+
+#: src/components/modal/index.tsx:84
+#, c-format
+msgid "Close"
+msgstr ""
+
+#: src/components/modal/index.tsx:124
+#, c-format
+msgid "Continue"
+msgstr ""
+
+#: src/components/modal/index.tsx:178
+#, c-format
+msgid "Clear"
+msgstr ""
+
+#: src/components/modal/index.tsx:190
+#, c-format
+msgid "Confirm"
+msgstr ""
+
+#: src/components/modal/index.tsx:296
+#, c-format
+msgid "is not the same as the current access token"
+msgstr ""
+
+#: src/components/modal/index.tsx:299
+#, c-format
+msgid "cannot be empty"
+msgstr ""
+
+#: src/components/modal/index.tsx:301
+#, c-format
+msgid "cannot be the same as the old token"
+msgstr ""
+
+#: src/components/modal/index.tsx:305
+#, c-format
+msgid "is not the same"
+msgstr ""
+
+#: src/components/modal/index.tsx:315
+#, c-format
+msgid "You are updating the access token from instance with id %1$s"
+msgstr ""
+
+#: src/components/modal/index.tsx:331
+#, c-format
+msgid "Old access token"
+msgstr ""
+
+#: src/components/modal/index.tsx:332
+#, c-format
+msgid "access token currently in use"
+msgstr ""
+
+#: src/components/modal/index.tsx:338
+#, c-format
+msgid "New access token"
+msgstr ""
+
+#: src/components/modal/index.tsx:339
+#, c-format
+msgid "next access token to be used"
+msgstr ""
+
+#: src/components/modal/index.tsx:344
+#, c-format
+msgid "Repeat access token"
+msgstr ""
+
+#: src/components/modal/index.tsx:345
+#, c-format
+msgid "confirm the same access token"
+msgstr ""
+
+#: src/components/modal/index.tsx:350
+#, c-format
+msgid "Clearing the access token will mean public access to the instance"
+msgstr ""
+
+#: src/components/modal/index.tsx:377
+#, c-format
+msgid "cannot be the same as the old access token"
+msgstr ""
+
+#: src/components/modal/index.tsx:394
+#, c-format
+msgid "You are setting the access token for the new instance"
+msgstr ""
+
+#: src/components/modal/index.tsx:420
+#, c-format
+msgid ""
+"With external authorization method no check will be done by the merchant "
+"backend"
+msgstr ""
+
+#: src/components/modal/index.tsx:436
+#, c-format
+msgid "Set external authorization"
+msgstr ""
+
+#: src/components/modal/index.tsx:448
+#, c-format
+msgid "Set access token"
+msgstr ""
+
+#: src/components/modal/index.tsx:470
+#, c-format
+msgid "Operation in progress..."
+msgstr ""
+
+#: src/components/modal/index.tsx:479
+#, c-format
+msgid "The operation will be automatically canceled after %1$s seconds"
+msgstr ""
+
+#: src/paths/admin/list/TableActive.tsx:80
+#, c-format
+msgid "Instances"
+msgstr ""
+
+#: src/paths/admin/list/TableActive.tsx:93
+#, c-format
+msgid "Delete"
+msgstr ""
+
+#: src/paths/admin/list/TableActive.tsx:99
+#, c-format
+msgid "add new instance"
+msgstr ""
+
+#: src/paths/admin/list/TableActive.tsx:178
+#, c-format
+msgid "ID"
+msgstr ""
+
+#: src/paths/admin/list/TableActive.tsx:181
+#, c-format
+msgid "Name"
+msgstr ""
+
+#: src/paths/admin/list/TableActive.tsx:220
+#, c-format
+msgid "Edit"
+msgstr ""
+
+#: src/paths/admin/list/TableActive.tsx:237
+#, c-format
+msgid "Purge"
+msgstr ""
+
+#: src/paths/admin/list/TableActive.tsx:261
+#, c-format
+msgid "There is no instances yet, add more pressing the + sign"
+msgstr ""
+
+#: src/paths/admin/list/View.tsx:68
+#, c-format
+msgid "Only show active instances"
+msgstr ""
+
+#: src/paths/admin/list/View.tsx:71
+#, c-format
+msgid "Active"
+msgstr ""
+
+#: src/paths/admin/list/View.tsx:78
+#, c-format
+msgid "Only show deleted instances"
+msgstr ""
+
+#: src/paths/admin/list/View.tsx:81
+#, c-format
+msgid "Deleted"
+msgstr ""
+
+#: src/paths/admin/list/View.tsx:88
+#, c-format
+msgid "Show all instances"
+msgstr ""
+
+#: src/paths/admin/list/View.tsx:91
+#, c-format
+msgid "All"
+msgstr ""
+
+#: src/paths/admin/list/index.tsx:101
+#, c-format
+msgid "Instance \"%1$s\" (ID: %2$s) has been deleted"
+msgstr ""
+
+#: src/paths/admin/list/index.tsx:106
+#, c-format
+msgid "Failed to delete instance"
+msgstr ""
+
+#: src/paths/admin/list/index.tsx:124
+#, c-format
+msgid "Instance '%1$s' (ID: %2$s) has been disabled"
+msgstr ""
+
+#: src/paths/admin/list/index.tsx:129
+#, c-format
+msgid "Failed to purge instance"
+msgstr ""
+
+#: src/paths/instance/kyc/list/ListPage.tsx:41
+#, c-format
+msgid "Pending KYC verification"
+msgstr ""
+
+#: src/paths/instance/kyc/list/ListPage.tsx:66
+#, c-format
+msgid "Timed out"
+msgstr ""
+
+#: src/paths/instance/kyc/list/ListPage.tsx:103
+#, c-format
+msgid "Exchange"
+msgstr ""
+
+#: src/paths/instance/kyc/list/ListPage.tsx:106
+#, c-format
+msgid "Target account"
+msgstr ""
+
+#: src/paths/instance/kyc/list/ListPage.tsx:109
+#, c-format
+msgid "KYC URL"
+msgstr ""
+
+#: src/paths/instance/kyc/list/ListPage.tsx:144
+#, c-format
+msgid "Code"
+msgstr ""
+
+#: src/paths/instance/kyc/list/ListPage.tsx:147
+#, c-format
+msgid "Http Status"
+msgstr ""
+
+#: src/paths/instance/kyc/list/ListPage.tsx:177
+#, c-format
+msgid "No pending kyc verification!"
+msgstr ""
+
+#: src/components/form/InputDate.tsx:123
+#, c-format
+msgid "change value to unknown date"
+msgstr ""
+
+#: src/components/form/InputDate.tsx:124
+#, c-format
+msgid "change value to empty"
+msgstr ""
+
+#: src/components/form/InputDate.tsx:131
+#, c-format
+msgid "clear"
+msgstr ""
+
+#: src/components/form/InputDate.tsx:136
+#, c-format
+msgid "change value to never"
+msgstr ""
+
+#: src/components/form/InputDate.tsx:141
+#, c-format
+msgid "never"
+msgstr ""
+
+#: src/components/form/InputLocation.tsx:29
+#, c-format
+msgid "Country"
+msgstr ""
+
+#: src/components/form/InputLocation.tsx:33
+#, c-format
+msgid "Address"
+msgstr ""
+
+#: src/components/form/InputLocation.tsx:39
+#, c-format
+msgid "Building number"
+msgstr ""
+
+#: src/components/form/InputLocation.tsx:41
+#, c-format
+msgid "Building name"
+msgstr ""
+
+#: src/components/form/InputLocation.tsx:42
+#, c-format
+msgid "Street"
+msgstr ""
+
+#: src/components/form/InputLocation.tsx:43
+#, c-format
+msgid "Post code"
+msgstr ""
+
+#: src/components/form/InputLocation.tsx:44
+#, c-format
+msgid "Town location"
+msgstr ""
+
+#: src/components/form/InputLocation.tsx:45
+#, c-format
+msgid "Town"
+msgstr ""
+
+#: src/components/form/InputLocation.tsx:46
+#, c-format
+msgid "District"
+msgstr ""
+
+#: src/components/form/InputLocation.tsx:49
+#, c-format
+msgid "Country subdivision"
+msgstr ""
+
+#: src/components/form/InputSearchProduct.tsx:66
+#, c-format
+msgid "Product id"
+msgstr ""
+
+#: src/components/form/InputSearchProduct.tsx:69
+#, c-format
+msgid "Description"
+msgstr ""
+
+#: src/components/form/InputSearchProduct.tsx:94
+#, c-format
+msgid "Product"
+msgstr ""
+
+#: src/components/form/InputSearchProduct.tsx:95
+#, c-format
+msgid "search products by it's description or id"
+msgstr ""
+
+#: src/components/form/InputSearchProduct.tsx:151
+#, c-format
+msgid "no products found with that description"
+msgstr ""
+
+#: src/components/product/InventoryProductForm.tsx:56
+#, c-format
+msgid "You must enter a valid product identifier."
+msgstr ""
+
+#: src/components/product/InventoryProductForm.tsx:64
+#, c-format
+msgid "Quantity must be greater than 0!"
+msgstr ""
+
+#: src/components/product/InventoryProductForm.tsx:76
+#, c-format
+msgid ""
+"This quantity exceeds remaining stock. Currently, only %1$s units remain "
+"unreserved in stock."
+msgstr ""
+
+#: src/components/product/InventoryProductForm.tsx:109
+#, c-format
+msgid "Quantity"
+msgstr ""
+
+#: src/components/product/InventoryProductForm.tsx:110
+#, c-format
+msgid "how many products will be added"
+msgstr ""
+
+#: src/components/product/InventoryProductForm.tsx:117
+#, c-format
+msgid "Add from inventory"
+msgstr ""
+
+#: src/components/form/InputImage.tsx:105
+#, c-format
+msgid "Image should be smaller than 1 MB"
+msgstr ""
+
+#: src/components/form/InputImage.tsx:110
+#, c-format
+msgid "Add"
+msgstr ""
+
+#: src/components/form/InputImage.tsx:115
+#, c-format
+msgid "Remove"
+msgstr ""
+
+#: src/components/form/InputTaxes.tsx:113
+#, c-format
+msgid "No taxes configured for this product."
+msgstr ""
+
+#: src/components/form/InputTaxes.tsx:119
+#, c-format
+msgid "Amount"
+msgstr ""
+
+#: src/components/form/InputTaxes.tsx:120
+#, c-format
+msgid ""
+"Taxes can be in currencies that differ from the main currency used by the "
+"merchant."
+msgstr ""
+
+#: src/components/form/InputTaxes.tsx:122
+#, c-format
+msgid ""
+"Enter currency and value separated with a colon, e.g. &quot;USD:2.3&quot;."
+msgstr ""
+
+#: src/components/form/InputTaxes.tsx:131
+#, c-format
+msgid "Legal name of the tax, e.g. VAT or import duties."
+msgstr ""
+
+#: src/components/form/InputTaxes.tsx:137
+#, c-format
+msgid "add tax to the tax list"
+msgstr ""
+
+#: src/components/product/NonInventoryProductForm.tsx:72
+#, c-format
+msgid "describe and add a product that is not in the inventory list"
+msgstr ""
+
+#: src/components/product/NonInventoryProductForm.tsx:75
+#, c-format
+msgid "Add custom product"
+msgstr ""
+
+#: src/components/product/NonInventoryProductForm.tsx:86
+#, c-format
+msgid "Complete information of the product"
+msgstr ""
+
+#: src/components/product/NonInventoryProductForm.tsx:185
+#, c-format
+msgid "Image"
+msgstr ""
+
+#: src/components/product/NonInventoryProductForm.tsx:186
+#, c-format
+msgid "photo of the product"
+msgstr ""
+
+#: src/components/product/NonInventoryProductForm.tsx:192
+#, c-format
+msgid "full product description"
+msgstr ""
+
+#: src/components/product/NonInventoryProductForm.tsx:196
+#, c-format
+msgid "Unit"
+msgstr ""
+
+#: src/components/product/NonInventoryProductForm.tsx:197
+#, c-format
+msgid "name of the product unit"
+msgstr ""
+
+#: src/components/product/NonInventoryProductForm.tsx:201
+#, c-format
+msgid "Price"
+msgstr ""
+
+#: src/components/product/NonInventoryProductForm.tsx:202
+#, c-format
+msgid "amount in the current currency"
+msgstr ""
+
+#: src/components/product/NonInventoryProductForm.tsx:211
+#, c-format
+msgid "Taxes"
+msgstr ""
+
+#: src/components/product/ProductList.tsx:38
+#, c-format
+msgid "image"
+msgstr ""
+
+#: src/components/product/ProductList.tsx:41
+#, c-format
+msgid "description"
+msgstr ""
+
+#: src/components/product/ProductList.tsx:44
+#, c-format
+msgid "quantity"
+msgstr ""
+
+#: src/components/product/ProductList.tsx:47
+#, c-format
+msgid "unit price"
+msgstr ""
+
+#: src/components/product/ProductList.tsx:50
+#, c-format
+msgid "total price"
+msgstr ""
+
+#: src/paths/instance/orders/create/CreatePage.tsx:153
+#, c-format
+msgid "required"
+msgstr ""
+
+#: src/paths/instance/orders/create/CreatePage.tsx:157
+#, c-format
+msgid "not valid"
+msgstr ""
+
+#: src/paths/instance/orders/create/CreatePage.tsx:159
+#, c-format
+msgid "must be greater than 0"
+msgstr ""
+
+#: src/paths/instance/orders/create/CreatePage.tsx:164
+#, c-format
+msgid "not a valid json"
+msgstr ""
+
+#: src/paths/instance/orders/create/CreatePage.tsx:170
+#, c-format
+msgid "should be in the future"
+msgstr ""
+
+#: src/paths/instance/orders/create/CreatePage.tsx:173
+#, c-format
+msgid "refund deadline cannot be before pay deadline"
+msgstr ""
+
+#: src/paths/instance/orders/create/CreatePage.tsx:179
+#, c-format
+msgid "wire transfer deadline cannot be before refund deadline"
+msgstr ""
+
+#: src/paths/instance/orders/create/CreatePage.tsx:190
+#, c-format
+msgid "wire transfer deadline cannot be before pay deadline"
+msgstr ""
+
+#: src/paths/instance/orders/create/CreatePage.tsx:197
+#, c-format
+msgid "should have a refund deadline"
+msgstr ""
+
+#: src/paths/instance/orders/create/CreatePage.tsx:202
+#, c-format
+msgid "auto refund cannot be after refund deadline"
+msgstr ""
+
+#: src/paths/instance/orders/create/CreatePage.tsx:360
+#, c-format
+msgid "Manage products in order"
+msgstr ""
+
+#: src/paths/instance/orders/create/CreatePage.tsx:369
+#, c-format
+msgid "Manage list of products in the order."
+msgstr ""
+
+#: src/paths/instance/orders/create/CreatePage.tsx:391
+#, c-format
+msgid "Remove this product from the order."
+msgstr ""
+
+#: src/paths/instance/orders/create/CreatePage.tsx:415
+#, c-format
+msgid "Total price"
+msgstr ""
+
+#: src/paths/instance/orders/create/CreatePage.tsx:417
+#, c-format
+msgid "total product price added up"
+msgstr ""
+
+#: src/paths/instance/orders/create/CreatePage.tsx:430
+#, c-format
+msgid "Amount to be paid by the customer"
+msgstr ""
+
+#: src/paths/instance/orders/create/CreatePage.tsx:436
+#, c-format
+msgid "Order price"
+msgstr ""
+
+#: src/paths/instance/orders/create/CreatePage.tsx:437
+#, c-format
+msgid "final order price"
+msgstr ""
+
+#: src/paths/instance/orders/create/CreatePage.tsx:444
+#, c-format
+msgid "Summary"
+msgstr ""
+
+#: src/paths/instance/orders/create/CreatePage.tsx:445
+#, c-format
+msgid "Title of the order to be shown to the customer"
+msgstr ""
+
+#: src/paths/instance/orders/create/CreatePage.tsx:450
+#, c-format
+msgid "Shipping and Fulfillment"
+msgstr ""
+
+#: src/paths/instance/orders/create/CreatePage.tsx:455
+#, c-format
+msgid "Delivery date"
+msgstr ""
+
+#: src/paths/instance/orders/create/CreatePage.tsx:456
+#, c-format
+msgid "Deadline for physical delivery assured by the merchant."
+msgstr ""
+
+#: src/paths/instance/orders/create/CreatePage.tsx:461
+#, c-format
+msgid "Location"
+msgstr ""
+
+#: src/paths/instance/orders/create/CreatePage.tsx:462
+#, c-format
+msgid "address where the products will be delivered"
+msgstr ""
+
+#: src/paths/instance/orders/create/CreatePage.tsx:469
+#, c-format
+msgid "Fulfillment URL"
+msgstr ""
+
+#: src/paths/instance/orders/create/CreatePage.tsx:470
+#, c-format
+msgid "URL to which the user will be redirected after successful payment."
+msgstr ""
+
+#: src/paths/instance/orders/create/CreatePage.tsx:476
+#, c-format
+msgid "Taler payment options"
+msgstr ""
+
+#: src/paths/instance/orders/create/CreatePage.tsx:477
+#, c-format
+msgid "Override default Taler payment settings for this order"
+msgstr ""
+
+#: src/paths/instance/orders/create/CreatePage.tsx:481
+#, c-format
+msgid "Payment deadline"
+msgstr ""
+
+#: src/paths/instance/orders/create/CreatePage.tsx:482
+#, c-format
+msgid ""
+"Deadline for the customer to pay for the offer before it expires. Inventory "
+"products will be reserved until this deadline."
+msgstr ""
+
+#: src/paths/instance/orders/create/CreatePage.tsx:486
+#, c-format
+msgid "Refund deadline"
+msgstr ""
+
+#: src/paths/instance/orders/create/CreatePage.tsx:487
+#, c-format
+msgid "Time until which the order can be refunded by the merchant."
+msgstr ""
+
+#: src/paths/instance/orders/create/CreatePage.tsx:491
+#, c-format
+msgid "Wire transfer deadline"
+msgstr ""
+
+#: src/paths/instance/orders/create/CreatePage.tsx:492
+#, c-format
+msgid "Deadline for the exchange to make the wire transfer."
+msgstr ""
+
+#: src/paths/instance/orders/create/CreatePage.tsx:496
+#, c-format
+msgid "Auto-refund deadline"
+msgstr ""
+
+#: src/paths/instance/orders/create/CreatePage.tsx:497
+#, c-format
+msgid ""
+"Time until which the wallet will automatically check for refunds without "
+"user interaction."
+msgstr ""
+
+#: src/paths/instance/orders/create/CreatePage.tsx:502
+#, c-format
+msgid "Maximum deposit fee"
+msgstr ""
+
+#: src/paths/instance/orders/create/CreatePage.tsx:503
+#, c-format
+msgid ""
+"Maximum deposit fees the merchant is willing to cover for this order. Higher "
+"deposit fees must be covered in full by the consumer."
+msgstr ""
+
+#: src/paths/instance/orders/create/CreatePage.tsx:507
+#, c-format
+msgid "Maximum wire fee"
+msgstr ""
+
+#: src/paths/instance/orders/create/CreatePage.tsx:508
+#, c-format
+msgid ""
+"Maximum aggregate wire fees the merchant is willing to cover for this order. "
+"Wire fees exceeding this amount are to be covered by the customers."
+msgstr ""
+
+#: src/paths/instance/orders/create/CreatePage.tsx:512
+#, c-format
+msgid "Wire fee amortization"
+msgstr ""
+
+#: src/paths/instance/orders/create/CreatePage.tsx:513
+#, c-format
+msgid ""
+"Factor by which wire fees exceeding the above threshold are divided to "
+"determine the share of excess wire fees to be paid explicitly by the "
+"consumer."
+msgstr ""
+
+#: src/paths/instance/orders/create/CreatePage.tsx:517
+#, c-format
+msgid "Create token"
+msgstr ""
+
+#: src/paths/instance/orders/create/CreatePage.tsx:518
+#, c-format
+msgid ""
+"Uncheck this option if the merchant backend generated an order ID with "
+"enough entropy to prevent adversarial claims."
+msgstr ""
+
+#: src/paths/instance/orders/create/CreatePage.tsx:522
+#, c-format
+msgid "Minimum age required"
+msgstr ""
+
+#: src/paths/instance/orders/create/CreatePage.tsx:523
+#, c-format
+msgid ""
+"Any value greater than 0 will limit the coins able be used to pay this "
+"contract. If empty the age restriction will be defined by the products"
+msgstr ""
+
+#: src/paths/instance/orders/create/CreatePage.tsx:526
+#, c-format
+msgid "Min age defined by the producs is %1$s"
+msgstr ""
+
+#: src/paths/instance/orders/create/CreatePage.tsx:534
+#, c-format
+msgid "Additional information"
+msgstr ""
+
+#: src/paths/instance/orders/create/CreatePage.tsx:535
+#, c-format
+msgid "Custom information to be included in the contract for this order."
+msgstr ""
+
+#: src/paths/instance/orders/create/CreatePage.tsx:541
+#, c-format
+msgid "You must enter a value in JavaScript Object Notation (JSON)."
+msgstr ""
+
+#: src/components/picker/DurationPicker.tsx:55
+#, c-format
+msgid "days"
+msgstr ""
+
+#: src/components/picker/DurationPicker.tsx:65
+#, c-format
+msgid "hours"
+msgstr ""
+
+#: src/components/picker/DurationPicker.tsx:76
+#, c-format
+msgid "minutes"
+msgstr ""
+
+#: src/components/picker/DurationPicker.tsx:87
+#, c-format
+msgid "seconds"
+msgstr ""
+
+#: src/components/form/InputDuration.tsx:53
+#, c-format
+msgid "forever"
+msgstr ""
+
+#: src/components/form/InputDuration.tsx:62
+#, c-format
+msgid "%1$sM"
+msgstr ""
+
+#: src/components/form/InputDuration.tsx:64
+#, c-format
+msgid "%1$sY"
+msgstr ""
+
+#: src/components/form/InputDuration.tsx:66
+#, c-format
+msgid "%1$sd"
+msgstr ""
+
+#: src/components/form/InputDuration.tsx:68
+#, c-format
+msgid "%1$sh"
+msgstr ""
+
+#: src/components/form/InputDuration.tsx:70
+#, c-format
+msgid "%1$smin"
+msgstr ""
+
+#: src/components/form/InputDuration.tsx:72
+#, c-format
+msgid "%1$ssec"
+msgstr ""
+
+#: src/paths/instance/orders/list/Table.tsx:75
+#, c-format
+msgid "Orders"
+msgstr ""
+
+#: src/paths/instance/orders/list/Table.tsx:81
+#, c-format
+msgid "create order"
+msgstr ""
+
+#: src/paths/instance/orders/list/Table.tsx:147
+#, c-format
+msgid "load newer orders"
+msgstr ""
+
+#: src/paths/instance/orders/list/Table.tsx:154
+#, c-format
+msgid "Date"
+msgstr ""
+
+#: src/paths/instance/orders/list/Table.tsx:200
+#, c-format
+msgid "Refund"
+msgstr ""
+
+#: src/paths/instance/orders/list/Table.tsx:209
+#, c-format
+msgid "copy url"
+msgstr ""
+
+#: src/paths/instance/orders/list/Table.tsx:225
+#, c-format
+msgid "load older orders"
+msgstr ""
+
+#: src/paths/instance/orders/list/Table.tsx:242
+#, c-format
+msgid "No orders have been found matching your query!"
+msgstr ""
+
+#: src/paths/instance/orders/list/Table.tsx:288
+#, c-format
+msgid "duplicated"
+msgstr ""
+
+#: src/paths/instance/orders/list/Table.tsx:299
+#, c-format
+msgid "invalid format"
+msgstr ""
+
+#: src/paths/instance/orders/list/Table.tsx:301
+#, c-format
+msgid "this value exceed the refundable amount"
+msgstr ""
+
+#: src/paths/instance/orders/list/Table.tsx:346
+#, c-format
+msgid "date"
+msgstr ""
+
+#: src/paths/instance/orders/list/Table.tsx:349
+#, c-format
+msgid "amount"
+msgstr ""
+
+#: src/paths/instance/orders/list/Table.tsx:352
+#, c-format
+msgid "reason"
+msgstr ""
+
+#: src/paths/instance/orders/list/Table.tsx:389
+#, c-format
+msgid "amount to be refunded"
+msgstr ""
+
+#: src/paths/instance/orders/list/Table.tsx:391
+#, c-format
+msgid "Max refundable:"
+msgstr ""
+
+#: src/paths/instance/orders/list/Table.tsx:396
+#, c-format
+msgid "Reason"
+msgstr ""
+
+#: src/paths/instance/orders/list/Table.tsx:397
+#, c-format
+msgid "Choose one..."
+msgstr ""
+
+#: src/paths/instance/orders/list/Table.tsx:399
+#, c-format
+msgid "requested by the customer"
+msgstr ""
+
+#: src/paths/instance/orders/list/Table.tsx:400
+#, c-format
+msgid "other"
+msgstr ""
+
+#: src/paths/instance/orders/list/Table.tsx:403
+#, c-format
+msgid "why this order is being refunded"
+msgstr ""
+
+#: src/paths/instance/orders/list/Table.tsx:409
+#, c-format
+msgid "more information to give context"
+msgstr ""
+
+#: src/paths/instance/orders/details/DetailPage.tsx:62
+#, c-format
+msgid "Contract Terms"
+msgstr ""
+
+#: src/paths/instance/orders/details/DetailPage.tsx:68
+#, c-format
+msgid "human-readable description of the whole purchase"
+msgstr ""
+
+#: src/paths/instance/orders/details/DetailPage.tsx:74
+#, c-format
+msgid "total price for the transaction"
+msgstr ""
+
+#: src/paths/instance/orders/details/DetailPage.tsx:81
+#, c-format
+msgid "URL for this purchase"
+msgstr ""
+
+#: src/paths/instance/orders/details/DetailPage.tsx:87
+#, c-format
+msgid "Max fee"
+msgstr ""
+
+#: src/paths/instance/orders/details/DetailPage.tsx:88
+#, c-format
+msgid "maximum total deposit fee accepted by the merchant for this contract"
+msgstr ""
+
+#: src/paths/instance/orders/details/DetailPage.tsx:93
+#, c-format
+msgid "Max wire fee"
+msgstr ""
+
+#: src/paths/instance/orders/details/DetailPage.tsx:94
+#, c-format
+msgid "maximum wire fee accepted by the merchant"
+msgstr ""
+
+#: src/paths/instance/orders/details/DetailPage.tsx:100
+#, c-format
+msgid ""
+"over how many customer transactions does the merchant expect to amortize "
+"wire fees on average"
+msgstr ""
+
+#: src/paths/instance/orders/details/DetailPage.tsx:105
+#, c-format
+msgid "Created at"
+msgstr ""
+
+#: src/paths/instance/orders/details/DetailPage.tsx:106
+#, c-format
+msgid "time when this contract was generated"
+msgstr ""
+
+#: src/paths/instance/orders/details/DetailPage.tsx:112
+#, c-format
+msgid "after this deadline has passed no refunds will be accepted"
+msgstr ""
+
+#: src/paths/instance/orders/details/DetailPage.tsx:118
+#, c-format
+msgid ""
+"after this deadline, the merchant won't accept payments for the contract"
+msgstr ""
+
+#: src/paths/instance/orders/details/DetailPage.tsx:124
+#, c-format
+msgid "transfer deadline for the exchange"
+msgstr ""
+
+#: src/paths/instance/orders/details/DetailPage.tsx:130
+#, c-format
+msgid "time indicating when the order should be delivered"
+msgstr ""
+
+#: src/paths/instance/orders/details/DetailPage.tsx:136
+#, c-format
+msgid "where the order will be delivered"
+msgstr ""
+
+#: src/paths/instance/orders/details/DetailPage.tsx:144
+#, c-format
+msgid "Auto-refund delay"
+msgstr ""
+
+#: src/paths/instance/orders/details/DetailPage.tsx:145
+#, c-format
+msgid ""
+"how long the wallet should try to get an automatic refund for the purchase"
+msgstr ""
+
+#: src/paths/instance/orders/details/DetailPage.tsx:150
+#, c-format
+msgid "Extra info"
+msgstr ""
+
+#: src/paths/instance/orders/details/DetailPage.tsx:151
+#, c-format
+msgid "extra data that is only interpreted by the merchant frontend"
+msgstr ""
+
+#: src/paths/instance/orders/details/DetailPage.tsx:219
+#, c-format
+msgid "Order"
+msgstr ""
+
+#: src/paths/instance/orders/details/DetailPage.tsx:221
+#, c-format
+msgid "claimed"
+msgstr ""
+
+#: src/paths/instance/orders/details/DetailPage.tsx:247
+#, c-format
+msgid "claimed at"
+msgstr ""
+
+#: src/paths/instance/orders/details/DetailPage.tsx:265
+#, c-format
+msgid "Timeline"
+msgstr ""
+
+#: src/paths/instance/orders/details/DetailPage.tsx:271
+#, c-format
+msgid "Payment details"
+msgstr ""
+
+#: src/paths/instance/orders/details/DetailPage.tsx:291
+#, c-format
+msgid "Order status"
+msgstr ""
+
+#: src/paths/instance/orders/details/DetailPage.tsx:301
+#, c-format
+msgid "Product list"
+msgstr ""
+
+#: src/paths/instance/orders/details/DetailPage.tsx:451
+#, c-format
+msgid "paid"
+msgstr ""
+
+#: src/paths/instance/orders/details/DetailPage.tsx:455
+#, c-format
+msgid "wired"
+msgstr ""
+
+#: src/paths/instance/orders/details/DetailPage.tsx:460
+#, c-format
+msgid "refunded"
+msgstr ""
+
+#: src/paths/instance/orders/details/DetailPage.tsx:480
+#, c-format
+msgid "refund order"
+msgstr ""
+
+#: src/paths/instance/orders/details/DetailPage.tsx:481
+#, c-format
+msgid "not refundable"
+msgstr ""
+
+#: src/paths/instance/orders/details/DetailPage.tsx:489
+#, c-format
+msgid "refund"
+msgstr ""
+
+#: src/paths/instance/orders/details/DetailPage.tsx:553
+#, c-format
+msgid "Refunded amount"
+msgstr ""
+
+#: src/paths/instance/orders/details/DetailPage.tsx:560
+#, c-format
+msgid "Refund taken"
+msgstr ""
+
+#: src/paths/instance/orders/details/DetailPage.tsx:570
+#, c-format
+msgid "Status URL"
+msgstr ""
+
+#: src/paths/instance/orders/details/DetailPage.tsx:583
+#, c-format
+msgid "Refund URI"
+msgstr ""
+
+#: src/paths/instance/orders/details/DetailPage.tsx:636
+#, c-format
+msgid "unpaid"
+msgstr ""
+
+#: src/paths/instance/orders/details/DetailPage.tsx:654
+#, c-format
+msgid "pay at"
+msgstr ""
+
+#: src/paths/instance/orders/details/DetailPage.tsx:666
+#, c-format
+msgid "created at"
+msgstr ""
+
+#: src/paths/instance/orders/details/DetailPage.tsx:707
+#, c-format
+msgid "Order status URL"
+msgstr ""
+
+#: src/paths/instance/orders/details/DetailPage.tsx:711
+#, c-format
+msgid "Payment URI"
+msgstr ""
+
+#: src/paths/instance/orders/details/DetailPage.tsx:740
+#, c-format
+msgid ""
+"Unknown order status. This is an error, please contact the administrator."
+msgstr ""
+
+#: src/paths/instance/orders/details/DetailPage.tsx:767
+#, c-format
+msgid "Back"
+msgstr ""
+
+#: src/paths/instance/orders/details/index.tsx:79
+#, c-format
+msgid "refund created successfully"
+msgstr ""
+
+#: src/paths/instance/orders/details/index.tsx:85
+#, c-format
+msgid "could not create the refund"
+msgstr ""
+
+#: src/paths/instance/orders/list/ListPage.tsx:78
+#, c-format
+msgid "select date to show nearby orders"
+msgstr ""
+
+#: src/paths/instance/orders/list/ListPage.tsx:94
+#, c-format
+msgid "order id"
+msgstr ""
+
+#: src/paths/instance/orders/list/ListPage.tsx:100
+#, c-format
+msgid "jump to order with the given order ID"
+msgstr ""
+
+#: src/paths/instance/orders/list/ListPage.tsx:122
+#, c-format
+msgid "remove all filters"
+msgstr ""
+
+#: src/paths/instance/orders/list/ListPage.tsx:132
+#, c-format
+msgid "only show paid orders"
+msgstr ""
+
+#: src/paths/instance/orders/list/ListPage.tsx:135
+#, c-format
+msgid "Paid"
+msgstr ""
+
+#: src/paths/instance/orders/list/ListPage.tsx:142
+#, c-format
+msgid "only show orders with refunds"
+msgstr ""
+
+#: src/paths/instance/orders/list/ListPage.tsx:145
+#, c-format
+msgid "Refunded"
+msgstr ""
+
+#: src/paths/instance/orders/list/ListPage.tsx:152
+#, c-format
+msgid ""
+"only show orders where customers paid, but wire payments from payment "
+"provider are still pending"
+msgstr ""
+
+#: src/paths/instance/orders/list/ListPage.tsx:155
+#, c-format
+msgid "Not wired"
+msgstr ""
+
+#: src/paths/instance/orders/list/ListPage.tsx:170
+#, c-format
+msgid "clear date filter"
+msgstr ""
+
+#: src/paths/instance/orders/list/ListPage.tsx:184
+#, c-format
+msgid "date (YYYY/MM/DD)"
+msgstr ""
+
+#: src/paths/instance/orders/list/index.tsx:103
+#, c-format
+msgid "Enter an order id"
+msgstr ""
+
+#: src/paths/instance/orders/list/index.tsx:111
+#, c-format
+msgid "order not found"
+msgstr ""
+
+#: src/paths/instance/orders/list/index.tsx:178
+#, c-format
+msgid "could not get the order to refund"
+msgstr ""
+
+#: src/components/exception/AsyncButton.tsx:43
+#, c-format
+msgid "Loading..."
+msgstr ""
+
+#: src/components/form/InputStock.tsx:99
+#, c-format
+msgid ""
+"click here to configure the stock of the product, leave it as is and the "
+"backend will not control stock"
+msgstr ""
+
+#: src/components/form/InputStock.tsx:109
+#, c-format
+msgid "Manage stock"
+msgstr ""
+
+#: src/components/form/InputStock.tsx:115
+#, c-format
+msgid "this product has been configured without stock control"
+msgstr ""
+
+#: src/components/form/InputStock.tsx:119
+#, c-format
+msgid "Infinite"
+msgstr ""
+
+#: src/components/form/InputStock.tsx:136
+#, c-format
+msgid "lost cannot be greater than current and incoming (max %1$s)"
+msgstr ""
+
+#: src/components/form/InputStock.tsx:176
+#, c-format
+msgid "Incoming"
+msgstr ""
+
+#: src/components/form/InputStock.tsx:177
+#, c-format
+msgid "Lost"
+msgstr ""
+
+#: src/components/form/InputStock.tsx:192
+#, c-format
+msgid "Current"
+msgstr ""
+
+#: src/components/form/InputStock.tsx:196
+#, c-format
+msgid "remove stock control for this product"
+msgstr ""
+
+#: src/components/form/InputStock.tsx:202
+#, c-format
+msgid "without stock"
+msgstr ""
+
+#: src/components/form/InputStock.tsx:211
+#, c-format
+msgid "Next restock"
+msgstr ""
+
+#: src/components/form/InputStock.tsx:217
+#, c-format
+msgid "Delivery address"
+msgstr ""
+
+#: src/components/product/ProductForm.tsx:133
+#, c-format
+msgid "product identification to use in URLs (for internal use only)"
+msgstr ""
+
+#: src/components/product/ProductForm.tsx:139
+#, c-format
+msgid "illustration of the product for customers"
+msgstr ""
+
+#: src/components/product/ProductForm.tsx:145
+#, c-format
+msgid "product description for customers"
+msgstr ""
+
+#: src/components/product/ProductForm.tsx:149
+#, c-format
+msgid "Age restricted"
+msgstr ""
+
+#: src/components/product/ProductForm.tsx:150
+#, c-format
+msgid "is this product restricted for customer below certain age?"
+msgstr ""
+
+#: src/components/product/ProductForm.tsx:155
+#, c-format
+msgid ""
+"unit describing quantity of product sold (e.g. 2 kilograms, 5 liters, 3 "
+"items, 5 meters) for customers"
+msgstr ""
+
+#: src/components/product/ProductForm.tsx:160
+#, c-format
+msgid ""
+"sale price for customers, including taxes, for above units of the product"
+msgstr ""
+
+#: src/components/product/ProductForm.tsx:164
+#, c-format
+msgid "Stock"
+msgstr ""
+
+#: src/components/product/ProductForm.tsx:166
+#, c-format
+msgid ""
+"product inventory for products with finite supply (for internal use only)"
+msgstr ""
+
+#: src/components/product/ProductForm.tsx:171
+#, c-format
+msgid "taxes included in the product price, exposed to customers"
+msgstr ""
+
+#: src/paths/instance/products/create/CreatePage.tsx:66
+#, c-format
+msgid "Need to complete marked fields"
+msgstr ""
+
+#: src/paths/instance/products/create/index.tsx:51
+#, c-format
+msgid "could not create product"
+msgstr ""
+
+#: src/paths/instance/products/list/Table.tsx:68
+#, c-format
+msgid "Products"
+msgstr ""
+
+#: src/paths/instance/products/list/Table.tsx:73
+#, c-format
+msgid "add product to inventory"
+msgstr ""
+
+#: src/paths/instance/products/list/Table.tsx:137
+#, c-format
+msgid "Sell"
+msgstr ""
+
+#: src/paths/instance/products/list/Table.tsx:143
+#, c-format
+msgid "Profit"
+msgstr ""
+
+#: src/paths/instance/products/list/Table.tsx:149
+#, c-format
+msgid "Sold"
+msgstr ""
+
+#: src/paths/instance/products/list/Table.tsx:210
+#, c-format
+msgid "free"
+msgstr ""
+
+#: src/paths/instance/products/list/Table.tsx:248
+#, c-format
+msgid "go to product update page"
+msgstr ""
+
+#: src/paths/instance/products/list/Table.tsx:255
+#, c-format
+msgid "Update"
+msgstr ""
+
+#: src/paths/instance/products/list/Table.tsx:260
+#, c-format
+msgid "remove this product from the database"
+msgstr ""
+
+#: src/paths/instance/products/list/Table.tsx:331
+#, c-format
+msgid "update the product with new price"
+msgstr ""
+
+#: src/paths/instance/products/list/Table.tsx:341
+#, c-format
+msgid "update product with new price"
+msgstr ""
+
+#: src/paths/instance/products/list/Table.tsx:399
+#, c-format
+msgid "add more elements to the inventory"
+msgstr ""
+
+#: src/paths/instance/products/list/Table.tsx:404
+#, c-format
+msgid "report elements lost in the inventory"
+msgstr ""
+
+#: src/paths/instance/products/list/Table.tsx:409
+#, c-format
+msgid "new price for the product"
+msgstr ""
+
+#: src/paths/instance/products/list/Table.tsx:421
+#, c-format
+msgid "the are value with errors"
+msgstr ""
+
+#: src/paths/instance/products/list/Table.tsx:422
+#, c-format
+msgid "update product with new stock and price"
+msgstr ""
+
+#: src/paths/instance/products/list/Table.tsx:463
+#, c-format
+msgid "There is no products yet, add more pressing the + sign"
+msgstr ""
+
+#: src/paths/instance/products/list/index.tsx:86
+#, c-format
+msgid "product updated successfully"
+msgstr ""
+
+#: src/paths/instance/products/list/index.tsx:92
+#, c-format
+msgid "could not update the product"
+msgstr ""
+
+#: src/paths/instance/products/list/index.tsx:103
+#, c-format
+msgid "product delete successfully"
+msgstr ""
+
+#: src/paths/instance/products/list/index.tsx:109
+#, c-format
+msgid "could not delete the product"
+msgstr ""
+
+#: src/paths/instance/products/update/UpdatePage.tsx:56
+#, c-format
+msgid "Product id:"
+msgstr ""
+
+#: src/paths/instance/reserves/create/CreatedSuccessfully.tsx:95
+#, c-format
+msgid ""
+"To complete the setup of the reserve, you must now initiate a wire transfer "
+"using the given wire transfer subject and crediting the specified amount to "
+"the indicated account of the exchange."
+msgstr ""
+
+#: src/paths/instance/reserves/create/CreatedSuccessfully.tsx:102
+#, c-format
+msgid "If your system supports RFC 8905, you can do this by opening this URI:"
+msgstr ""
+
+#: src/paths/instance/reserves/create/CreatePage.tsx:83
+#, c-format
+msgid "it should be greater than 0"
+msgstr ""
+
+#: src/paths/instance/reserves/create/CreatePage.tsx:88
+#, c-format
+msgid "must be a valid URL"
+msgstr ""
+
+#: src/paths/instance/reserves/create/CreatePage.tsx:107
+#, c-format
+msgid "Initial balance"
+msgstr ""
+
+#: src/paths/instance/reserves/create/CreatePage.tsx:108
+#, c-format
+msgid "balance prior to deposit"
+msgstr ""
+
+#: src/paths/instance/reserves/create/CreatePage.tsx:112
+#, c-format
+msgid "Exchange URL"
+msgstr ""
+
+#: src/paths/instance/reserves/create/CreatePage.tsx:113
+#, c-format
+msgid "URL of exchange"
+msgstr ""
+
+#: src/paths/instance/reserves/create/CreatePage.tsx:148
+#, c-format
+msgid "Next"
+msgstr ""
+
+#: src/paths/instance/reserves/create/CreatePage.tsx:186
+#, c-format
+msgid "Wire method"
+msgstr ""
+
+#: src/paths/instance/reserves/create/CreatePage.tsx:187
+#, c-format
+msgid "method to use for wire transfer"
+msgstr ""
+
+#: src/paths/instance/reserves/create/CreatePage.tsx:189
+#, c-format
+msgid "Select one wire method"
+msgstr ""
+
+#: src/paths/instance/reserves/create/index.tsx:62
+#, c-format
+msgid "could not create reserve"
+msgstr ""
+
+#: src/paths/instance/reserves/details/DetailPage.tsx:77
+#, c-format
+msgid "Valid until"
+msgstr ""
+
+#: src/paths/instance/reserves/details/DetailPage.tsx:82
+#, c-format
+msgid "Created balance"
+msgstr ""
+
+#: src/paths/instance/reserves/details/DetailPage.tsx:99
+#, c-format
+msgid "Exchange balance"
+msgstr ""
+
+#: src/paths/instance/reserves/details/DetailPage.tsx:104
+#, c-format
+msgid "Picked up"
+msgstr ""
+
+#: src/paths/instance/reserves/details/DetailPage.tsx:109
+#, c-format
+msgid "Committed"
+msgstr ""
+
+#: src/paths/instance/reserves/details/DetailPage.tsx:116
+#, c-format
+msgid "Account address"
+msgstr ""
+
+#: src/paths/instance/reserves/details/DetailPage.tsx:119
+#, c-format
+msgid "Subject"
+msgstr ""
+
+#: src/paths/instance/reserves/details/DetailPage.tsx:130
+#, c-format
+msgid "Tips"
+msgstr ""
+
+#: src/paths/instance/reserves/details/DetailPage.tsx:193
+#, c-format
+msgid "No tips has been authorized from this reserve"
+msgstr ""
+
+#: src/paths/instance/reserves/details/DetailPage.tsx:213
+#, c-format
+msgid "Authorized"
+msgstr ""
+
+#: src/paths/instance/reserves/details/DetailPage.tsx:222
+#, c-format
+msgid "Expiration"
+msgstr ""
+
+#: src/paths/instance/reserves/list/AutorizeTipModal.tsx:108
+#, c-format
+msgid "amount of tip"
+msgstr ""
+
+#: src/paths/instance/reserves/list/AutorizeTipModal.tsx:112
+#, c-format
+msgid "Justification"
+msgstr ""
+
+#: src/paths/instance/reserves/list/AutorizeTipModal.tsx:114
+#, c-format
+msgid "reason for the tip"
+msgstr ""
+
+#: src/paths/instance/reserves/list/AutorizeTipModal.tsx:118
+#, c-format
+msgid "URL after tip"
+msgstr ""
+
+#: src/paths/instance/reserves/list/AutorizeTipModal.tsx:119
+#, c-format
+msgid "URL to visit after tip payment"
+msgstr ""
+
+#: src/paths/instance/reserves/list/Table.tsx:65
+#, c-format
+msgid "Reserves not yet funded"
+msgstr ""
+
+#: src/paths/instance/reserves/list/Table.tsx:89
+#, c-format
+msgid "Reserves ready"
+msgstr ""
+
+#: src/paths/instance/reserves/list/Table.tsx:95
+#, c-format
+msgid "add new reserve"
+msgstr ""
+
+#: src/paths/instance/reserves/list/Table.tsx:143
+#, c-format
+msgid "Expires at"
+msgstr ""
+
+#: src/paths/instance/reserves/list/Table.tsx:146
+#, c-format
+msgid "Initial"
+msgstr ""
+
+#: src/paths/instance/reserves/list/Table.tsx:202
+#, c-format
+msgid "delete selected reserve from the database"
+msgstr ""
+
+#: src/paths/instance/reserves/list/Table.tsx:210
+#, c-format
+msgid "authorize new tip from selected reserve"
+msgstr ""
+
+#: src/paths/instance/reserves/list/Table.tsx:237
+#, c-format
+msgid ""
+"There is no ready reserves yet, add more pressing the + sign or fund them"
+msgstr ""
+
+#: src/paths/instance/reserves/list/Table.tsx:264
+#, c-format
+msgid "Expected Balance"
+msgstr ""
+
+#: src/paths/instance/reserves/list/index.tsx:110
+#, c-format
+msgid "could not create the tip"
+msgstr ""
+
+#: src/paths/instance/templates/create/CreatePage.tsx:77
+#, c-format
+msgid "should not be empty"
+msgstr ""
+
+#: src/paths/instance/templates/create/CreatePage.tsx:93
+#, c-format
+msgid "should be greater that 0"
+msgstr ""
+
+#: src/paths/instance/templates/create/CreatePage.tsx:96
+#, c-format
+msgid "can't be empty"
+msgstr ""
+
+#: src/paths/instance/templates/create/CreatePage.tsx:100
+#, c-format
+msgid "to short"
+msgstr ""
+
+#: src/paths/instance/templates/create/CreatePage.tsx:108
+#, c-format
+msgid "just letters and numbers from 2 to 7"
+msgstr ""
+
+#: src/paths/instance/templates/create/CreatePage.tsx:110
+#, c-format
+msgid "size of the key should be 32"
+msgstr ""
+
+#: src/paths/instance/templates/create/CreatePage.tsx:137
+#, c-format
+msgid "Identifier"
+msgstr ""
+
+#: src/paths/instance/templates/create/CreatePage.tsx:138
+#, c-format
+msgid "Name of the template in URLs."
+msgstr ""
+
+#: src/paths/instance/templates/create/CreatePage.tsx:144
+#, c-format
+msgid "Describe what this template stands for"
+msgstr ""
+
+#: src/paths/instance/templates/create/CreatePage.tsx:149
+#, c-format
+msgid "Fixed summary"
+msgstr ""
+
+#: src/paths/instance/templates/create/CreatePage.tsx:150
+#, c-format
+msgid "If specified, this template will create order with the same summary"
+msgstr ""
+
+#: src/paths/instance/templates/create/CreatePage.tsx:154
+#, c-format
+msgid "Fixed price"
+msgstr ""
+
+#: src/paths/instance/templates/create/CreatePage.tsx:155
+#, c-format
+msgid "If specified, this template will create order with the same price"
+msgstr ""
+
+#: src/paths/instance/templates/create/CreatePage.tsx:159
+#, c-format
+msgid "Minimum age"
+msgstr ""
+
+#: src/paths/instance/templates/create/CreatePage.tsx:161
+#, c-format
+msgid "Is this contract restricted to some age?"
+msgstr ""
+
+#: src/paths/instance/templates/create/CreatePage.tsx:165
+#, c-format
+msgid "Payment timeout"
+msgstr ""
+
+#: src/paths/instance/templates/create/CreatePage.tsx:167
+#, c-format
+msgid ""
+"How much time has the customer to complete the payment once the order was "
+"created."
+msgstr ""
+
+#: src/paths/instance/templates/create/CreatePage.tsx:171
+#, c-format
+msgid "Verification algorithm"
+msgstr ""
+
+#: src/paths/instance/templates/create/CreatePage.tsx:172
+#, c-format
+msgid "Algorithm to use to verify transaction in offline mode"
+msgstr ""
+
+#: src/paths/instance/templates/create/CreatePage.tsx:180
+#, c-format
+msgid "Point-of-sale key"
+msgstr ""
+
+#: src/paths/instance/templates/create/CreatePage.tsx:182
+#, c-format
+msgid "Useful to validate the purchase"
+msgstr ""
+
+#: src/paths/instance/templates/create/CreatePage.tsx:196
+#, c-format
+msgid "generate random secret key"
+msgstr ""
+
+#: src/paths/instance/templates/create/CreatePage.tsx:203
+#, c-format
+msgid "random"
+msgstr ""
+
+#: src/paths/instance/templates/create/CreatePage.tsx:208
+#, c-format
+msgid "show secret key"
+msgstr ""
+
+#: src/paths/instance/templates/create/CreatePage.tsx:209
+#, c-format
+msgid "hide secret key"
+msgstr ""
+
+#: src/paths/instance/templates/create/CreatePage.tsx:216
+#, c-format
+msgid "hide"
+msgstr ""
+
+#: src/paths/instance/templates/create/CreatePage.tsx:218
+#, c-format
+msgid "show"
+msgstr ""
+
+#: src/paths/instance/templates/create/index.tsx:52
+#, c-format
+msgid "could not inform template"
+msgstr ""
+
+#: src/paths/instance/templates/use/UsePage.tsx:54
+#, c-format
+msgid "Amount is required"
+msgstr ""
+
+#: src/paths/instance/templates/use/UsePage.tsx:58
+#, c-format
+msgid "Order summary is required"
+msgstr ""
+
+#: src/paths/instance/templates/use/UsePage.tsx:86
+#, c-format
+msgid "New order for template"
+msgstr ""
+
+#: src/paths/instance/templates/use/UsePage.tsx:108
+#, c-format
+msgid "Amount of the order"
+msgstr ""
+
+#: src/paths/instance/templates/use/UsePage.tsx:113
+#, c-format
+msgid "Order summary"
+msgstr ""
+
+#: src/paths/instance/templates/use/index.tsx:92
+#, c-format
+msgid "could not create order from template"
+msgstr ""
+
+#: src/paths/instance/templates/qr/QrPage.tsx:131
+#, c-format
+msgid ""
+"Here you can specify a default value for fields that are not fixed. Default "
+"values can be edited by the customer before the payment."
+msgstr ""
+
+#: src/paths/instance/templates/qr/QrPage.tsx:148
+#, c-format
+msgid "Fixed amount"
+msgstr ""
+
+#: src/paths/instance/templates/qr/QrPage.tsx:149
+#, c-format
+msgid "Default amount"
+msgstr ""
+
+#: src/paths/instance/templates/qr/QrPage.tsx:161
+#, c-format
+msgid "Default summary"
+msgstr ""
+
+#: src/paths/instance/templates/qr/QrPage.tsx:177
+#, c-format
+msgid "Print"
+msgstr ""
+
+#: src/paths/instance/templates/qr/QrPage.tsx:184
+#, c-format
+msgid "Setup TOTP"
+msgstr ""
+
+#: src/paths/instance/templates/list/Table.tsx:65
+#, c-format
+msgid "Templates"
+msgstr ""
+
+#: src/paths/instance/templates/list/Table.tsx:70
+#, c-format
+msgid "add new templates"
+msgstr ""
+
+#: src/paths/instance/templates/list/Table.tsx:142
+#, c-format
+msgid "load more templates before the first one"
+msgstr ""
+
+#: src/paths/instance/templates/list/Table.tsx:146
+#, c-format
+msgid "load newer templates"
+msgstr ""
+
+#: src/paths/instance/templates/list/Table.tsx:181
+#, c-format
+msgid "delete selected templates from the database"
+msgstr ""
+
+#: src/paths/instance/templates/list/Table.tsx:188
+#, c-format
+msgid "use template to create new order"
+msgstr ""
+
+#: src/paths/instance/templates/list/Table.tsx:195
+#, c-format
+msgid "create qr code for the template"
+msgstr ""
+
+#: src/paths/instance/templates/list/Table.tsx:210
+#, c-format
+msgid "load more templates after the last one"
+msgstr ""
+
+#: src/paths/instance/templates/list/Table.tsx:214
+#, c-format
+msgid "load older templates"
+msgstr ""
+
+#: src/paths/instance/templates/list/Table.tsx:231
+#, c-format
+msgid "There is no templates yet, add more pressing the + sign"
+msgstr ""
+
+#: src/paths/instance/templates/list/index.tsx:104
+#, c-format
+msgid "template delete successfully"
+msgstr ""
+
+#: src/paths/instance/templates/list/index.tsx:110
+#, c-format
+msgid "could not delete the template"
+msgstr ""
+
+#: src/paths/instance/templates/update/index.tsx:90
+#, c-format
+msgid "could not update template"
+msgstr ""
+
+#: src/paths/instance/webhooks/create/CreatePage.tsx:57
+#, c-format
+msgid "should be one of '%1$s'"
+msgstr ""
+
+#: src/paths/instance/webhooks/create/CreatePage.tsx:85
+#, c-format
+msgid "Webhook ID to use"
+msgstr ""
+
+#: src/paths/instance/webhooks/create/CreatePage.tsx:89
+#, c-format
+msgid "Event"
+msgstr ""
+
+#: src/paths/instance/webhooks/create/CreatePage.tsx:90
+#, c-format
+msgid "The event of the webhook: why the webhook is used"
+msgstr ""
+
+#: src/paths/instance/webhooks/create/CreatePage.tsx:94
+#, c-format
+msgid "Method"
+msgstr ""
+
+#: src/paths/instance/webhooks/create/CreatePage.tsx:95
+#, c-format
+msgid "Method used by the webhook"
+msgstr ""
+
+#: src/paths/instance/webhooks/create/CreatePage.tsx:99
+#, c-format
+msgid "URL"
+msgstr ""
+
+#: src/paths/instance/webhooks/create/CreatePage.tsx:100
+#, c-format
+msgid "URL of the webhook where the customer will be redirected"
+msgstr ""
+
+#: src/paths/instance/webhooks/create/CreatePage.tsx:104
+#, c-format
+msgid "Header"
+msgstr ""
+
+#: src/paths/instance/webhooks/create/CreatePage.tsx:106
+#, c-format
+msgid "Header template of the webhook"
+msgstr ""
+
+#: src/paths/instance/webhooks/create/CreatePage.tsx:111
+#, c-format
+msgid "Body"
+msgstr ""
+
+#: src/paths/instance/webhooks/create/CreatePage.tsx:112
+#, c-format
+msgid "Body template by the webhook"
+msgstr ""
+
+#: src/paths/instance/webhooks/list/Table.tsx:61
+#, c-format
+msgid "Webhooks"
+msgstr ""
+
+#: src/paths/instance/webhooks/list/Table.tsx:66
+#, c-format
+msgid "add new webhooks"
+msgstr ""
+
+#: src/paths/instance/webhooks/list/Table.tsx:137
+#, c-format
+msgid "load more webhooks before the first one"
+msgstr ""
+
+#: src/paths/instance/webhooks/list/Table.tsx:141
+#, c-format
+msgid "load newer webhooks"
+msgstr ""
+
+#: src/paths/instance/webhooks/list/Table.tsx:151
+#, c-format
+msgid "Event type"
+msgstr ""
+
+#: src/paths/instance/webhooks/list/Table.tsx:176
+#, c-format
+msgid "delete selected webhook from the database"
+msgstr ""
+
+#: src/paths/instance/webhooks/list/Table.tsx:198
+#, c-format
+msgid "load more webhooks after the last one"
+msgstr ""
+
+#: src/paths/instance/webhooks/list/Table.tsx:202
+#, c-format
+msgid "load older webhooks"
+msgstr ""
+
+#: src/paths/instance/webhooks/list/Table.tsx:219
+#, c-format
+msgid "There is no webhooks yet, add more pressing the + sign"
+msgstr ""
+
+#: src/paths/instance/webhooks/list/index.tsx:94
+#, c-format
+msgid "webhook delete successfully"
+msgstr ""
+
+#: src/paths/instance/webhooks/list/index.tsx:100
+#, c-format
+msgid "could not delete the webhook"
+msgstr ""
+
+#: src/paths/instance/transfers/create/CreatePage.tsx:63
+#, c-format
+msgid "check the id, does not look valid"
+msgstr ""
+
+#: src/paths/instance/transfers/create/CreatePage.tsx:65
+#, c-format
+msgid "should have 52 characters, current %1$s"
+msgstr ""
+
+#: src/paths/instance/transfers/create/CreatePage.tsx:72
+#, c-format
+msgid "URL doesn't have the right format"
+msgstr ""
+
+#: src/paths/instance/transfers/create/CreatePage.tsx:98
+#, c-format
+msgid "Credited bank account"
+msgstr ""
+
+#: src/paths/instance/transfers/create/CreatePage.tsx:100
+#, c-format
+msgid "Select one account"
+msgstr ""
+
+#: src/paths/instance/transfers/create/CreatePage.tsx:101
+#, c-format
+msgid "Bank account of the merchant where the payment was received"
+msgstr ""
+
+#: src/paths/instance/transfers/create/CreatePage.tsx:105
+#, c-format
+msgid "Wire transfer ID"
+msgstr ""
+
+#: src/paths/instance/transfers/create/CreatePage.tsx:107
+#, c-format
+msgid ""
+"unique identifier of the wire transfer used by the exchange, must be 52 "
+"characters long"
+msgstr ""
+
+#: src/paths/instance/transfers/create/CreatePage.tsx:112
+#, c-format
+msgid ""
+"Base URL of the exchange that made the transfer, should have been in the "
+"wire transfer subject"
+msgstr ""
+
+#: src/paths/instance/transfers/create/CreatePage.tsx:117
+#, c-format
+msgid "Amount credited"
+msgstr ""
+
+#: src/paths/instance/transfers/create/CreatePage.tsx:118
+#, c-format
+msgid "Actual amount that was wired to the merchant's bank account"
+msgstr ""
+
+#: src/paths/instance/transfers/create/index.tsx:58
+#, c-format
+msgid "could not inform transfer"
+msgstr ""
+
+#: src/paths/instance/transfers/list/Table.tsx:61
+#, c-format
+msgid "Transfers"
+msgstr ""
+
+#: src/paths/instance/transfers/list/Table.tsx:66
+#, c-format
+msgid "add new transfer"
+msgstr ""
+
+#: src/paths/instance/transfers/list/Table.tsx:129
+#, c-format
+msgid "load more transfers before the first one"
+msgstr ""
+
+#: src/paths/instance/transfers/list/Table.tsx:133
+#, c-format
+msgid "load newer transfers"
+msgstr ""
+
+#: src/paths/instance/transfers/list/Table.tsx:143
+#, c-format
+msgid "Credit"
+msgstr ""
+
+#: src/paths/instance/transfers/list/Table.tsx:152
+#, c-format
+msgid "Confirmed"
+msgstr ""
+
+#: src/paths/instance/transfers/list/Table.tsx:155
+#, c-format
+msgid "Verified"
+msgstr ""
+
+#: src/paths/instance/transfers/list/Table.tsx:158
+#, c-format
+msgid "Executed at"
+msgstr ""
+
+#: src/paths/instance/transfers/list/Table.tsx:171
+#, c-format
+msgid "yes"
+msgstr ""
+
+#: src/paths/instance/transfers/list/Table.tsx:171
+#, c-format
+msgid "no"
+msgstr ""
+
+#: src/paths/instance/transfers/list/Table.tsx:181
+#, c-format
+msgid "unknown"
+msgstr ""
+
+#: src/paths/instance/transfers/list/Table.tsx:187
+#, c-format
+msgid "delete selected transfer from the database"
+msgstr ""
+
+#: src/paths/instance/transfers/list/Table.tsx:202
+#, c-format
+msgid "load more transfer after the last one"
+msgstr ""
+
+#: src/paths/instance/transfers/list/Table.tsx:206
+#, c-format
+msgid "load older transfers"
+msgstr ""
+
+#: src/paths/instance/transfers/list/Table.tsx:223
+#, c-format
+msgid "There is no transfer yet, add more pressing the + sign"
+msgstr ""
+
+#: src/paths/instance/transfers/list/ListPage.tsx:79
+#, c-format
+msgid "filter by account address"
+msgstr ""
+
+#: src/paths/instance/transfers/list/ListPage.tsx:100
+#, c-format
+msgid "only show wire transfers confirmed by the merchant"
+msgstr ""
+
+#: src/paths/instance/transfers/list/ListPage.tsx:110
+#, c-format
+msgid "only show wire transfers claimed by the exchange"
+msgstr ""
+
+#: src/paths/instance/transfers/list/ListPage.tsx:113
+#, c-format
+msgid "Unverified"
+msgstr ""
+
+#: src/paths/admin/create/CreatePage.tsx:69
+#, c-format
+msgid "is not valid"
+msgstr ""
+
+#: src/paths/admin/create/CreatePage.tsx:94
+#, c-format
+msgid "is not a number"
+msgstr ""
+
+#: src/paths/admin/create/CreatePage.tsx:96
+#, c-format
+msgid "must be 1 or greater"
+msgstr ""
+
+#: src/paths/admin/create/CreatePage.tsx:107
+#, c-format
+msgid "max 7 lines"
+msgstr ""
+
+#: src/paths/admin/create/CreatePage.tsx:178
+#, c-format
+msgid "change authorization configuration"
+msgstr ""
+
+#: src/paths/admin/create/CreatePage.tsx:217
+#, c-format
+msgid "Need to complete marked fields and choose authorization method"
+msgstr ""
+
+#: src/components/form/InputPaytoForm.tsx:82
+#, c-format
+msgid "This is not a valid bitcoin address."
+msgstr ""
+
+#: src/components/form/InputPaytoForm.tsx:95
+#, c-format
+msgid "This is not a valid Ethereum address."
+msgstr ""
+
+#: src/components/form/InputPaytoForm.tsx:118
+#, c-format
+msgid "IBAN numbers usually have more that 4 digits"
+msgstr ""
+
+#: src/components/form/InputPaytoForm.tsx:120
+#, c-format
+msgid "IBAN numbers usually have less that 34 digits"
+msgstr ""
+
+#: src/components/form/InputPaytoForm.tsx:128
+#, c-format
+msgid "IBAN country code not found"
+msgstr ""
+
+#: src/components/form/InputPaytoForm.tsx:153
+#, c-format
+msgid "IBAN number is not valid, checksum is wrong"
+msgstr ""
+
+#: src/components/form/InputPaytoForm.tsx:248
+#, c-format
+msgid "Target type"
+msgstr ""
+
+#: src/components/form/InputPaytoForm.tsx:249
+#, c-format
+msgid "Method to use for wire transfer"
+msgstr ""
+
+#: src/components/form/InputPaytoForm.tsx:258
+#, c-format
+msgid "Routing"
+msgstr ""
+
+#: src/components/form/InputPaytoForm.tsx:259
+#, c-format
+msgid "Routing number."
+msgstr ""
+
+#: src/components/form/InputPaytoForm.tsx:263
+#, c-format
+msgid "Account"
+msgstr ""
+
+#: src/components/form/InputPaytoForm.tsx:264
+#, c-format
+msgid "Account number."
+msgstr ""
+
+#: src/components/form/InputPaytoForm.tsx:273
+#, c-format
+msgid "Business Identifier Code."
+msgstr ""
+
+#: src/components/form/InputPaytoForm.tsx:282
+#, c-format
+msgid "Bank Account Number."
+msgstr ""
+
+#: src/components/form/InputPaytoForm.tsx:292
+#, c-format
+msgid "Unified Payment Interface."
+msgstr ""
+
+#: src/components/form/InputPaytoForm.tsx:301
+#, c-format
+msgid "Bitcoin protocol."
+msgstr ""
+
+#: src/components/form/InputPaytoForm.tsx:310
+#, c-format
+msgid "Ethereum protocol."
+msgstr ""
+
+#: src/components/form/InputPaytoForm.tsx:319
+#, c-format
+msgid "Interledger protocol."
+msgstr ""
+
+#: src/components/form/InputPaytoForm.tsx:328
+#, c-format
+msgid "Host"
+msgstr ""
+
+#: src/components/form/InputPaytoForm.tsx:329
+#, c-format
+msgid "Bank host."
+msgstr ""
+
+#: src/components/form/InputPaytoForm.tsx:334
+#, c-format
+msgid "Bank account."
+msgstr ""
+
+#: src/components/form/InputPaytoForm.tsx:343
+#, c-format
+msgid "Bank account owner's name."
+msgstr ""
+
+#: src/components/form/InputPaytoForm.tsx:370
+#, c-format
+msgid "No accounts yet."
+msgstr ""
+
+#: src/components/instance/DefaultInstanceFormFields.tsx:52
+#, c-format
+msgid ""
+"Name of the instance in URLs. The 'default' instance is special in that it "
+"is used to administer other instances."
+msgstr ""
+
+#: src/components/instance/DefaultInstanceFormFields.tsx:58
+#, c-format
+msgid "Business name"
+msgstr ""
+
+#: src/components/instance/DefaultInstanceFormFields.tsx:59
+#, c-format
+msgid "Legal name of the business represented by this instance."
+msgstr ""
+
+#: src/components/instance/DefaultInstanceFormFields.tsx:64
+#, c-format
+msgid "Email"
+msgstr ""
+
+#: src/components/instance/DefaultInstanceFormFields.tsx:65
+#, c-format
+msgid "Contact email"
+msgstr ""
+
+#: src/components/instance/DefaultInstanceFormFields.tsx:70
+#, c-format
+msgid "Website URL"
+msgstr ""
+
+#: src/components/instance/DefaultInstanceFormFields.tsx:71
+#, c-format
+msgid "URL."
+msgstr ""
+
+#: src/components/instance/DefaultInstanceFormFields.tsx:76
+#, c-format
+msgid "Logo"
+msgstr ""
+
+#: src/components/instance/DefaultInstanceFormFields.tsx:77
+#, c-format
+msgid "Logo image."
+msgstr ""
+
+#: src/components/instance/DefaultInstanceFormFields.tsx:82
+#, c-format
+msgid "Bank account"
+msgstr ""
+
+#: src/components/instance/DefaultInstanceFormFields.tsx:83
+#, c-format
+msgid "URI specifying bank account for crediting revenue."
+msgstr ""
+
+#: src/components/instance/DefaultInstanceFormFields.tsx:88
+#, c-format
+msgid "Default max deposit fee"
+msgstr ""
+
+#: src/components/instance/DefaultInstanceFormFields.tsx:89
+#, c-format
+msgid ""
+"Maximum deposit fees this merchant is willing to pay per order by default."
+msgstr ""
+
+#: src/components/instance/DefaultInstanceFormFields.tsx:94
+#, c-format
+msgid "Default max wire fee"
+msgstr ""
+
+#: src/components/instance/DefaultInstanceFormFields.tsx:95
+#, c-format
+msgid ""
+"Maximum wire fees this merchant is willing to pay per wire transfer by "
+"default."
+msgstr ""
+
+#: src/components/instance/DefaultInstanceFormFields.tsx:100
+#, c-format
+msgid "Default wire fee amortization"
+msgstr ""
+
+#: src/components/instance/DefaultInstanceFormFields.tsx:101
+#, c-format
+msgid ""
+"Number of orders excess wire transfer fees will be divided by to compute per "
+"order surcharge."
+msgstr ""
+
+#: src/components/instance/DefaultInstanceFormFields.tsx:107
+#, c-format
+msgid "Physical location of the merchant."
+msgstr ""
+
+#: src/components/instance/DefaultInstanceFormFields.tsx:114
+#, c-format
+msgid "Jurisdiction"
+msgstr ""
+
+#: src/components/instance/DefaultInstanceFormFields.tsx:115
+#, c-format
+msgid "Jurisdiction for legal disputes with the merchant."
+msgstr ""
+
+#: src/components/instance/DefaultInstanceFormFields.tsx:122
+#, c-format
+msgid "Default payment delay"
+msgstr ""
+
+#: src/components/instance/DefaultInstanceFormFields.tsx:124
+#, c-format
+msgid ""
+"Time customers have to pay an order before the offer expires by default."
+msgstr ""
+
+#: src/components/instance/DefaultInstanceFormFields.tsx:129
+#, c-format
+msgid "Default wire transfer delay"
+msgstr ""
+
+#: src/components/instance/DefaultInstanceFormFields.tsx:130
+#, c-format
+msgid ""
+"Maximum time an exchange is allowed to delay wiring funds to the merchant, "
+"enabling it to aggregate smaller payments into larger wire transfers and "
+"reducing wire fees."
+msgstr ""
+
+#: src/paths/instance/update/UpdatePage.tsx:164
+#, c-format
+msgid "Instance id"
+msgstr ""
+
+#: src/paths/instance/update/UpdatePage.tsx:173
+#, c-format
+msgid "Change the authorization method use for this instance."
+msgstr ""
+
+#: src/paths/instance/update/UpdatePage.tsx:182
+#, c-format
+msgid "Manage access token"
+msgstr ""
+
+#: src/paths/instance/update/index.tsx:112
+#, c-format
+msgid "Failed to create instance"
+msgstr ""
+
+#: src/components/exception/login.tsx:74
+#, c-format
+msgid "Login required"
+msgstr ""
+
+#: src/components/exception/login.tsx:80
+#, c-format
+msgid "Please enter your access token."
+msgstr ""
+
+#: src/components/exception/login.tsx:108
+#, c-format
+msgid "Access Token"
+msgstr ""
+
+#: src/InstanceRoutes.tsx:171
+#, c-format
+msgid "The request to the backend take too long and was cancelled"
+msgstr ""
+
+#: src/InstanceRoutes.tsx:172
+#, c-format
+msgid "Diagnostic from %1$s is \"%2$s\""
+msgstr ""
+
+#: src/InstanceRoutes.tsx:178
+#, c-format
+msgid "The backend reported a problem: HTTP status #%1$s"
+msgstr ""
+
+#: src/InstanceRoutes.tsx:179
+#, c-format
+msgid "Diagnostic from %1$s is '%2$s'"
+msgstr ""
+
+#: src/InstanceRoutes.tsx:196
+#, c-format
+msgid "Access denied"
+msgstr ""
+
+#: src/InstanceRoutes.tsx:197
+#, c-format
+msgid "The access token provided is invalid."
+msgstr ""
+
+#: src/InstanceRoutes.tsx:212
+#, c-format
+msgid "No 'default' instance configured yet."
+msgstr ""
+
+#: src/InstanceRoutes.tsx:213
+#, c-format
+msgid "Create a 'default' instance to begin using the merchant backoffice."
+msgstr ""
+
+#: src/InstanceRoutes.tsx:630
+#, c-format
+msgid "The access token provided is invalid"
+msgstr ""
+
+#: src/InstanceRoutes.tsx:664
+#, c-format
+msgid "Hide for today"
+msgstr ""
+
+#: src/components/menu/SideBar.tsx:82
+#, c-format
+msgid "Instance"
+msgstr ""
+
+#: src/components/menu/SideBar.tsx:91
+#, c-format
+msgid "Settings"
+msgstr ""
+
+#: src/components/menu/SideBar.tsx:167
+#, c-format
+msgid "Connection"
+msgstr ""
+
+#: src/components/menu/SideBar.tsx:209
+#, c-format
+msgid "New"
+msgstr ""
+
+#: src/components/menu/SideBar.tsx:219
+#, c-format
+msgid "List"
+msgstr ""
+
+#: src/components/menu/SideBar.tsx:234
+#, c-format
+msgid "Log out"
+msgstr ""
+
+#: src/ApplicationReadyRoutes.tsx:71
+#, c-format
+msgid "Check your token is valid"
+msgstr ""
+
+#: src/ApplicationReadyRoutes.tsx:90
+#, c-format
+msgid "Couldn't access the server."
+msgstr ""
+
+#: src/ApplicationReadyRoutes.tsx:91
+#, c-format
+msgid "Could not infer instance id from url %1$s"
+msgstr ""
+
+#: src/Application.tsx:104
+#, c-format
+msgid "Server not found"
+msgstr ""
+
+#: src/Application.tsx:118
+#, c-format
+msgid "Server response with an error code"
+msgstr ""
+
+#: src/Application.tsx:120
+#, c-format
+msgid "Got message %1$s from %2$s"
+msgstr ""
+
+#: src/Application.tsx:131
+#, c-format
+msgid "Response from server is unreadable, http status: %1$s"
+msgstr ""
+
+#: src/Application.tsx:144
+#, c-format
+msgid "Unexpected Error"
+msgstr ""
+
+#: src/components/form/InputArray.tsx:101
+#, c-format
+msgid "The value %1$s is invalid for a payment url"
+msgstr ""
+
+#: src/components/form/InputArray.tsx:110
+#, c-format
+msgid "add element to the list"
+msgstr ""
+
+#: src/components/form/InputArray.tsx:112
+#, c-format
+msgid "add"
+msgstr ""
+
+#: src/components/form/InputSecured.tsx:37
+#, c-format
+msgid "Deleting"
+msgstr ""
+
+#: src/components/form/InputSecured.tsx:41
+#, c-format
+msgid "Changing"
+msgstr ""
+
+#: src/paths/instance/orders/create/OrderCreatedSuccessfully.tsx:87
+#, c-format
+msgid "Order ID"
+msgstr ""
+
+#: src/paths/instance/orders/create/OrderCreatedSuccessfully.tsx:101
+#, c-format
+msgid "Payment URL"
+msgstr ""
diff --git 
a/packages/auditor-backoffice-ui/src/i18n/taler-merchant-backoffice.pot 
b/packages/auditor-backoffice-ui/src/i18n/taler-merchant-backoffice.pot
new file mode 100644
index 000000000..5ef56ca05
--- /dev/null
+++ b/packages/auditor-backoffice-ui/src/i18n/taler-merchant-backoffice.pot
@@ -0,0 +1,2726 @@
+#  This file is part of GNU Taler
+#  (C) 2021-2023 Taler Systems S.A.
+
+#  GNU Taler is free software; you can redistribute it and/or modify it under 
the
+#  terms of the GNU General Public License as published by the Free Software
+#  Foundation; either version 3, or (at your option) any later version.
+
+#  GNU Taler is distributed in the hope that it will be useful, but WITHOUT ANY
+#  WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS 
FOR
+#  A PARTICULAR PURPOSE.  See the GNU General Public License for more details.
+
+#  You should have received a copy of the GNU General Public License along with
+#  GNU Taler; see the file COPYING.  If not, see <http://www.gnu.org/licenses/>
+
+#
+#, fuzzy
+msgid ""
+msgstr ""
+"Project-Id-Version: Taler Wallet\n"
+"Report-Msgid-Bugs-To: taler@gnu.org\n"
+"PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n"
+"Last-Translator: FULL NAME <EMAIL@ADDRESS>\n"
+"Language-Team: LANGUAGE <LL@li.org>\n"
+"MIME-Version: 1.0\n"
+"Content-Type: text/plain; charset=UTF-8\n"
+"Content-Transfer-Encoding: 8bit\n"
+"Plural-Forms: nplurals=2; plural=(n != 1);\n"
+#: src/components/modal/index.tsx:71
+#, c-format
+msgid "Cancel"
+msgstr ""
+
+#: src/components/modal/index.tsx:79
+#, c-format
+msgid "%1$s"
+msgstr ""
+
+#: src/components/modal/index.tsx:84
+#, c-format
+msgid "Close"
+msgstr ""
+
+#: src/components/modal/index.tsx:124
+#, c-format
+msgid "Continue"
+msgstr ""
+
+#: src/components/modal/index.tsx:178
+#, c-format
+msgid "Clear"
+msgstr ""
+
+#: src/components/modal/index.tsx:190
+#, c-format
+msgid "Confirm"
+msgstr ""
+
+#: src/components/modal/index.tsx:296
+#, c-format
+msgid "is not the same as the current access token"
+msgstr ""
+
+#: src/components/modal/index.tsx:299
+#, c-format
+msgid "cannot be empty"
+msgstr ""
+
+#: src/components/modal/index.tsx:301
+#, c-format
+msgid "cannot be the same as the old token"
+msgstr ""
+
+#: src/components/modal/index.tsx:305
+#, c-format
+msgid "is not the same"
+msgstr ""
+
+#: src/components/modal/index.tsx:315
+#, c-format
+msgid "You are updating the access token from instance with id %1$s"
+msgstr ""
+
+#: src/components/modal/index.tsx:331
+#, c-format
+msgid "Old access token"
+msgstr ""
+
+#: src/components/modal/index.tsx:332
+#, c-format
+msgid "access token currently in use"
+msgstr ""
+
+#: src/components/modal/index.tsx:338
+#, c-format
+msgid "New access token"
+msgstr ""
+
+#: src/components/modal/index.tsx:339
+#, c-format
+msgid "next access token to be used"
+msgstr ""
+
+#: src/components/modal/index.tsx:344
+#, c-format
+msgid "Repeat access token"
+msgstr ""
+
+#: src/components/modal/index.tsx:345
+#, c-format
+msgid "confirm the same access token"
+msgstr ""
+
+#: src/components/modal/index.tsx:350
+#, c-format
+msgid "Clearing the access token will mean public access to the instance"
+msgstr ""
+
+#: src/components/modal/index.tsx:377
+#, c-format
+msgid "cannot be the same as the old access token"
+msgstr ""
+
+#: src/components/modal/index.tsx:394
+#, c-format
+msgid "You are setting the access token for the new instance"
+msgstr ""
+
+#: src/components/modal/index.tsx:420
+#, c-format
+msgid "With external authorization method no check will be done by the 
merchant backend"
+msgstr ""
+
+#: src/components/modal/index.tsx:436
+#, c-format
+msgid "Set external authorization"
+msgstr ""
+
+#: src/components/modal/index.tsx:448
+#, c-format
+msgid "Set access token"
+msgstr ""
+
+#: src/components/modal/index.tsx:470
+#, c-format
+msgid "Operation in progress..."
+msgstr ""
+
+#: src/components/modal/index.tsx:479
+#, c-format
+msgid "The operation will be automatically canceled after %1$s seconds"
+msgstr ""
+
+#: src/paths/admin/list/TableActive.tsx:80
+#, c-format
+msgid "Instances"
+msgstr ""
+
+#: src/paths/admin/list/TableActive.tsx:93
+#, c-format
+msgid "Delete"
+msgstr ""
+
+#: src/paths/admin/list/TableActive.tsx:99
+#, c-format
+msgid "add new instance"
+msgstr ""
+
+#: src/paths/admin/list/TableActive.tsx:178
+#, c-format
+msgid "ID"
+msgstr ""
+
+#: src/paths/admin/list/TableActive.tsx:181
+#, c-format
+msgid "Name"
+msgstr ""
+
+#: src/paths/admin/list/TableActive.tsx:220
+#, c-format
+msgid "Edit"
+msgstr ""
+
+#: src/paths/admin/list/TableActive.tsx:237
+#, c-format
+msgid "Purge"
+msgstr ""
+
+#: src/paths/admin/list/TableActive.tsx:261
+#, c-format
+msgid "There is no instances yet, add more pressing the + sign"
+msgstr ""
+
+#: src/paths/admin/list/View.tsx:68
+#, c-format
+msgid "Only show active instances"
+msgstr ""
+
+#: src/paths/admin/list/View.tsx:71
+#, c-format
+msgid "Active"
+msgstr ""
+
+#: src/paths/admin/list/View.tsx:78
+#, c-format
+msgid "Only show deleted instances"
+msgstr ""
+
+#: src/paths/admin/list/View.tsx:81
+#, c-format
+msgid "Deleted"
+msgstr ""
+
+#: src/paths/admin/list/View.tsx:88
+#, c-format
+msgid "Show all instances"
+msgstr ""
+
+#: src/paths/admin/list/View.tsx:91
+#, c-format
+msgid "All"
+msgstr ""
+
+#: src/paths/admin/list/index.tsx:101
+#, c-format
+msgid "Instance \"%1$s\" (ID: %2$s) has been deleted"
+msgstr ""
+
+#: src/paths/admin/list/index.tsx:106
+#, c-format
+msgid "Failed to delete instance"
+msgstr ""
+
+#: src/paths/admin/list/index.tsx:124
+#, c-format
+msgid "Instance '%1$s' (ID: %2$s) has been disabled"
+msgstr ""
+
+#: src/paths/admin/list/index.tsx:129
+#, c-format
+msgid "Failed to purge instance"
+msgstr ""
+
+#: src/paths/instance/kyc/list/ListPage.tsx:41
+#, c-format
+msgid "Pending KYC verification"
+msgstr ""
+
+#: src/paths/instance/kyc/list/ListPage.tsx:66
+#, c-format
+msgid "Timed out"
+msgstr ""
+
+#: src/paths/instance/kyc/list/ListPage.tsx:103
+#, c-format
+msgid "Exchange"
+msgstr ""
+
+#: src/paths/instance/kyc/list/ListPage.tsx:106
+#, c-format
+msgid "Target account"
+msgstr ""
+
+#: src/paths/instance/kyc/list/ListPage.tsx:109
+#, c-format
+msgid "KYC URL"
+msgstr ""
+
+#: src/paths/instance/kyc/list/ListPage.tsx:144
+#, c-format
+msgid "Code"
+msgstr ""
+
+#: src/paths/instance/kyc/list/ListPage.tsx:147
+#, c-format
+msgid "Http Status"
+msgstr ""
+
+#: src/paths/instance/kyc/list/ListPage.tsx:177
+#, c-format
+msgid "No pending kyc verification!"
+msgstr ""
+
+#: src/components/form/InputDate.tsx:123
+#, c-format
+msgid "change value to unknown date"
+msgstr ""
+
+#: src/components/form/InputDate.tsx:124
+#, c-format
+msgid "change value to empty"
+msgstr ""
+
+#: src/components/form/InputDate.tsx:131
+#, c-format
+msgid "clear"
+msgstr ""
+
+#: src/components/form/InputDate.tsx:136
+#, c-format
+msgid "change value to never"
+msgstr ""
+
+#: src/components/form/InputDate.tsx:141
+#, c-format
+msgid "never"
+msgstr ""
+
+#: src/components/form/InputLocation.tsx:29
+#, c-format
+msgid "Country"
+msgstr ""
+
+#: src/components/form/InputLocation.tsx:33
+#, c-format
+msgid "Address"
+msgstr ""
+
+#: src/components/form/InputLocation.tsx:39
+#, c-format
+msgid "Building number"
+msgstr ""
+
+#: src/components/form/InputLocation.tsx:41
+#, c-format
+msgid "Building name"
+msgstr ""
+
+#: src/components/form/InputLocation.tsx:42
+#, c-format
+msgid "Street"
+msgstr ""
+
+#: src/components/form/InputLocation.tsx:43
+#, c-format
+msgid "Post code"
+msgstr ""
+
+#: src/components/form/InputLocation.tsx:44
+#, c-format
+msgid "Town location"
+msgstr ""
+
+#: src/components/form/InputLocation.tsx:45
+#, c-format
+msgid "Town"
+msgstr ""
+
+#: src/components/form/InputLocation.tsx:46
+#, c-format
+msgid "District"
+msgstr ""
+
+#: src/components/form/InputLocation.tsx:49
+#, c-format
+msgid "Country subdivision"
+msgstr ""
+
+#: src/components/form/InputSearchProduct.tsx:66
+#, c-format
+msgid "Product id"
+msgstr ""
+
+#: src/components/form/InputSearchProduct.tsx:69
+#, c-format
+msgid "Description"
+msgstr ""
+
+#: src/components/form/InputSearchProduct.tsx:94
+#, c-format
+msgid "Product"
+msgstr ""
+
+#: src/components/form/InputSearchProduct.tsx:95
+#, c-format
+msgid "search products by it's description or id"
+msgstr ""
+
+#: src/components/form/InputSearchProduct.tsx:151
+#, c-format
+msgid "no products found with that description"
+msgstr ""
+
+#: src/components/product/InventoryProductForm.tsx:56
+#, c-format
+msgid "You must enter a valid product identifier."
+msgstr ""
+
+#: src/components/product/InventoryProductForm.tsx:64
+#, c-format
+msgid "Quantity must be greater than 0!"
+msgstr ""
+
+#: src/components/product/InventoryProductForm.tsx:76
+#, c-format
+msgid ""
+"This quantity exceeds remaining stock. Currently, only %1$s units remain "
+"unreserved in stock."
+msgstr ""
+
+#: src/components/product/InventoryProductForm.tsx:109
+#, c-format
+msgid "Quantity"
+msgstr ""
+
+#: src/components/product/InventoryProductForm.tsx:110
+#, c-format
+msgid "how many products will be added"
+msgstr ""
+
+#: src/components/product/InventoryProductForm.tsx:117
+#, c-format
+msgid "Add from inventory"
+msgstr ""
+
+#: src/components/form/InputImage.tsx:105
+#, c-format
+msgid "Image should be smaller than 1 MB"
+msgstr ""
+
+#: src/components/form/InputImage.tsx:110
+#, c-format
+msgid "Add"
+msgstr ""
+
+#: src/components/form/InputImage.tsx:115
+#, c-format
+msgid "Remove"
+msgstr ""
+
+#: src/components/form/InputTaxes.tsx:113
+#, c-format
+msgid "No taxes configured for this product."
+msgstr ""
+
+#: src/components/form/InputTaxes.tsx:119
+#, c-format
+msgid "Amount"
+msgstr ""
+
+#: src/components/form/InputTaxes.tsx:120
+#, c-format
+msgid ""
+"Taxes can be in currencies that differ from the main currency used by the "
+"merchant."
+msgstr ""
+
+#: src/components/form/InputTaxes.tsx:122
+#, c-format
+msgid "Enter currency and value separated with a colon, e.g. 
&quot;USD:2.3&quot;."
+msgstr ""
+
+#: src/components/form/InputTaxes.tsx:131
+#, c-format
+msgid "Legal name of the tax, e.g. VAT or import duties."
+msgstr ""
+
+#: src/components/form/InputTaxes.tsx:137
+#, c-format
+msgid "add tax to the tax list"
+msgstr ""
+
+#: src/components/product/NonInventoryProductForm.tsx:72
+#, c-format
+msgid "describe and add a product that is not in the inventory list"
+msgstr ""
+
+#: src/components/product/NonInventoryProductForm.tsx:75
+#, c-format
+msgid "Add custom product"
+msgstr ""
+
+#: src/components/product/NonInventoryProductForm.tsx:86
+#, c-format
+msgid "Complete information of the product"
+msgstr ""
+
+#: src/components/product/NonInventoryProductForm.tsx:185
+#, c-format
+msgid "Image"
+msgstr ""
+
+#: src/components/product/NonInventoryProductForm.tsx:186
+#, c-format
+msgid "photo of the product"
+msgstr ""
+
+#: src/components/product/NonInventoryProductForm.tsx:192
+#, c-format
+msgid "full product description"
+msgstr ""
+
+#: src/components/product/NonInventoryProductForm.tsx:196
+#, c-format
+msgid "Unit"
+msgstr ""
+
+#: src/components/product/NonInventoryProductForm.tsx:197
+#, c-format
+msgid "name of the product unit"
+msgstr ""
+
+#: src/components/product/NonInventoryProductForm.tsx:201
+#, c-format
+msgid "Price"
+msgstr ""
+
+#: src/components/product/NonInventoryProductForm.tsx:202
+#, c-format
+msgid "amount in the current currency"
+msgstr ""
+
+#: src/components/product/NonInventoryProductForm.tsx:211
+#, c-format
+msgid "Taxes"
+msgstr ""
+
+#: src/components/product/ProductList.tsx:38
+#, c-format
+msgid "image"
+msgstr ""
+
+#: src/components/product/ProductList.tsx:41
+#, c-format
+msgid "description"
+msgstr ""
+
+#: src/components/product/ProductList.tsx:44
+#, c-format
+msgid "quantity"
+msgstr ""
+
+#: src/components/product/ProductList.tsx:47
+#, c-format
+msgid "unit price"
+msgstr ""
+
+#: src/components/product/ProductList.tsx:50
+#, c-format
+msgid "total price"
+msgstr ""
+
+#: src/paths/instance/orders/create/CreatePage.tsx:153
+#, c-format
+msgid "required"
+msgstr ""
+
+#: src/paths/instance/orders/create/CreatePage.tsx:157
+#, c-format
+msgid "not valid"
+msgstr ""
+
+#: src/paths/instance/orders/create/CreatePage.tsx:159
+#, c-format
+msgid "must be greater than 0"
+msgstr ""
+
+#: src/paths/instance/orders/create/CreatePage.tsx:164
+#, c-format
+msgid "not a valid json"
+msgstr ""
+
+#: src/paths/instance/orders/create/CreatePage.tsx:170
+#, c-format
+msgid "should be in the future"
+msgstr ""
+
+#: src/paths/instance/orders/create/CreatePage.tsx:173
+#, c-format
+msgid "refund deadline cannot be before pay deadline"
+msgstr ""
+
+#: src/paths/instance/orders/create/CreatePage.tsx:179
+#, c-format
+msgid "wire transfer deadline cannot be before refund deadline"
+msgstr ""
+
+#: src/paths/instance/orders/create/CreatePage.tsx:190
+#, c-format
+msgid "wire transfer deadline cannot be before pay deadline"
+msgstr ""
+
+#: src/paths/instance/orders/create/CreatePage.tsx:197
+#, c-format
+msgid "should have a refund deadline"
+msgstr ""
+
+#: src/paths/instance/orders/create/CreatePage.tsx:202
+#, c-format
+msgid "auto refund cannot be after refund deadline"
+msgstr ""
+
+#: src/paths/instance/orders/create/CreatePage.tsx:360
+#, c-format
+msgid "Manage products in order"
+msgstr ""
+
+#: src/paths/instance/orders/create/CreatePage.tsx:369
+#, c-format
+msgid "Manage list of products in the order."
+msgstr ""
+
+#: src/paths/instance/orders/create/CreatePage.tsx:391
+#, c-format
+msgid "Remove this product from the order."
+msgstr ""
+
+#: src/paths/instance/orders/create/CreatePage.tsx:415
+#, c-format
+msgid "Total price"
+msgstr ""
+
+#: src/paths/instance/orders/create/CreatePage.tsx:417
+#, c-format
+msgid "total product price added up"
+msgstr ""
+
+#: src/paths/instance/orders/create/CreatePage.tsx:430
+#, c-format
+msgid "Amount to be paid by the customer"
+msgstr ""
+
+#: src/paths/instance/orders/create/CreatePage.tsx:436
+#, c-format
+msgid "Order price"
+msgstr ""
+
+#: src/paths/instance/orders/create/CreatePage.tsx:437
+#, c-format
+msgid "final order price"
+msgstr ""
+
+#: src/paths/instance/orders/create/CreatePage.tsx:444
+#, c-format
+msgid "Summary"
+msgstr ""
+
+#: src/paths/instance/orders/create/CreatePage.tsx:445
+#, c-format
+msgid "Title of the order to be shown to the customer"
+msgstr ""
+
+#: src/paths/instance/orders/create/CreatePage.tsx:450
+#, c-format
+msgid "Shipping and Fulfillment"
+msgstr ""
+
+#: src/paths/instance/orders/create/CreatePage.tsx:455
+#, c-format
+msgid "Delivery date"
+msgstr ""
+
+#: src/paths/instance/orders/create/CreatePage.tsx:456
+#, c-format
+msgid "Deadline for physical delivery assured by the merchant."
+msgstr ""
+
+#: src/paths/instance/orders/create/CreatePage.tsx:461
+#, c-format
+msgid "Location"
+msgstr ""
+
+#: src/paths/instance/orders/create/CreatePage.tsx:462
+#, c-format
+msgid "address where the products will be delivered"
+msgstr ""
+
+#: src/paths/instance/orders/create/CreatePage.tsx:469
+#, c-format
+msgid "Fulfillment URL"
+msgstr ""
+
+#: src/paths/instance/orders/create/CreatePage.tsx:470
+#, c-format
+msgid "URL to which the user will be redirected after successful payment."
+msgstr ""
+
+#: src/paths/instance/orders/create/CreatePage.tsx:476
+#, c-format
+msgid "Taler payment options"
+msgstr ""
+
+#: src/paths/instance/orders/create/CreatePage.tsx:477
+#, c-format
+msgid "Override default Taler payment settings for this order"
+msgstr ""
+
+#: src/paths/instance/orders/create/CreatePage.tsx:481
+#, c-format
+msgid "Payment deadline"
+msgstr ""
+
+#: src/paths/instance/orders/create/CreatePage.tsx:482
+#, c-format
+msgid ""
+"Deadline for the customer to pay for the offer before it expires. Inventory "
+"products will be reserved until this deadline."
+msgstr ""
+
+#: src/paths/instance/orders/create/CreatePage.tsx:486
+#, c-format
+msgid "Refund deadline"
+msgstr ""
+
+#: src/paths/instance/orders/create/CreatePage.tsx:487
+#, c-format
+msgid "Time until which the order can be refunded by the merchant."
+msgstr ""
+
+#: src/paths/instance/orders/create/CreatePage.tsx:491
+#, c-format
+msgid "Wire transfer deadline"
+msgstr ""
+
+#: src/paths/instance/orders/create/CreatePage.tsx:492
+#, c-format
+msgid "Deadline for the exchange to make the wire transfer."
+msgstr ""
+
+#: src/paths/instance/orders/create/CreatePage.tsx:496
+#, c-format
+msgid "Auto-refund deadline"
+msgstr ""
+
+#: src/paths/instance/orders/create/CreatePage.tsx:497
+#, c-format
+msgid ""
+"Time until which the wallet will automatically check for refunds without user 
"
+"interaction."
+msgstr ""
+
+#: src/paths/instance/orders/create/CreatePage.tsx:502
+#, c-format
+msgid "Maximum deposit fee"
+msgstr ""
+
+#: src/paths/instance/orders/create/CreatePage.tsx:503
+#, c-format
+msgid ""
+"Maximum deposit fees the merchant is willing to cover for this order. Higher "
+"deposit fees must be covered in full by the consumer."
+msgstr ""
+
+#: src/paths/instance/orders/create/CreatePage.tsx:507
+#, c-format
+msgid "Maximum wire fee"
+msgstr ""
+
+#: src/paths/instance/orders/create/CreatePage.tsx:508
+#, c-format
+msgid ""
+"Maximum aggregate wire fees the merchant is willing to cover for this order. "
+"Wire fees exceeding this amount are to be covered by the customers."
+msgstr ""
+
+#: src/paths/instance/orders/create/CreatePage.tsx:512
+#, c-format
+msgid "Wire fee amortization"
+msgstr ""
+
+#: src/paths/instance/orders/create/CreatePage.tsx:513
+#, c-format
+msgid ""
+"Factor by which wire fees exceeding the above threshold are divided to 
determine "
+"the share of excess wire fees to be paid explicitly by the consumer."
+msgstr ""
+
+#: src/paths/instance/orders/create/CreatePage.tsx:517
+#, c-format
+msgid "Create token"
+msgstr ""
+
+#: src/paths/instance/orders/create/CreatePage.tsx:518
+#, c-format
+msgid ""
+"Uncheck this option if the merchant backend generated an order ID with enough 
"
+"entropy to prevent adversarial claims."
+msgstr ""
+
+#: src/paths/instance/orders/create/CreatePage.tsx:522
+#, c-format
+msgid "Minimum age required"
+msgstr ""
+
+#: src/paths/instance/orders/create/CreatePage.tsx:523
+#, c-format
+msgid ""
+"Any value greater than 0 will limit the coins able be used to pay this 
contract. "
+"If empty the age restriction will be defined by the products"
+msgstr ""
+
+#: src/paths/instance/orders/create/CreatePage.tsx:526
+#, c-format
+msgid "Min age defined by the producs is %1$s"
+msgstr ""
+
+#: src/paths/instance/orders/create/CreatePage.tsx:534
+#, c-format
+msgid "Additional information"
+msgstr ""
+
+#: src/paths/instance/orders/create/CreatePage.tsx:535
+#, c-format
+msgid "Custom information to be included in the contract for this order."
+msgstr ""
+
+#: src/paths/instance/orders/create/CreatePage.tsx:541
+#, c-format
+msgid "You must enter a value in JavaScript Object Notation (JSON)."
+msgstr ""
+
+#: src/components/picker/DurationPicker.tsx:55
+#, c-format
+msgid "days"
+msgstr ""
+
+#: src/components/picker/DurationPicker.tsx:65
+#, c-format
+msgid "hours"
+msgstr ""
+
+#: src/components/picker/DurationPicker.tsx:76
+#, c-format
+msgid "minutes"
+msgstr ""
+
+#: src/components/picker/DurationPicker.tsx:87
+#, c-format
+msgid "seconds"
+msgstr ""
+
+#: src/components/form/InputDuration.tsx:53
+#, c-format
+msgid "forever"
+msgstr ""
+
+#: src/components/form/InputDuration.tsx:62
+#, c-format
+msgid "%1$sM"
+msgstr ""
+
+#: src/components/form/InputDuration.tsx:64
+#, c-format
+msgid "%1$sY"
+msgstr ""
+
+#: src/components/form/InputDuration.tsx:66
+#, c-format
+msgid "%1$sd"
+msgstr ""
+
+#: src/components/form/InputDuration.tsx:68
+#, c-format
+msgid "%1$sh"
+msgstr ""
+
+#: src/components/form/InputDuration.tsx:70
+#, c-format
+msgid "%1$smin"
+msgstr ""
+
+#: src/components/form/InputDuration.tsx:72
+#, c-format
+msgid "%1$ssec"
+msgstr ""
+
+#: src/paths/instance/orders/list/Table.tsx:75
+#, c-format
+msgid "Orders"
+msgstr ""
+
+#: src/paths/instance/orders/list/Table.tsx:81
+#, c-format
+msgid "create order"
+msgstr ""
+
+#: src/paths/instance/orders/list/Table.tsx:147
+#, c-format
+msgid "load newer orders"
+msgstr ""
+
+#: src/paths/instance/orders/list/Table.tsx:154
+#, c-format
+msgid "Date"
+msgstr ""
+
+#: src/paths/instance/orders/list/Table.tsx:200
+#, c-format
+msgid "Refund"
+msgstr ""
+
+#: src/paths/instance/orders/list/Table.tsx:209
+#, c-format
+msgid "copy url"
+msgstr ""
+
+#: src/paths/instance/orders/list/Table.tsx:225
+#, c-format
+msgid "load older orders"
+msgstr ""
+
+#: src/paths/instance/orders/list/Table.tsx:242
+#, c-format
+msgid "No orders have been found matching your query!"
+msgstr ""
+
+#: src/paths/instance/orders/list/Table.tsx:288
+#, c-format
+msgid "duplicated"
+msgstr ""
+
+#: src/paths/instance/orders/list/Table.tsx:299
+#, c-format
+msgid "invalid format"
+msgstr ""
+
+#: src/paths/instance/orders/list/Table.tsx:301
+#, c-format
+msgid "this value exceed the refundable amount"
+msgstr ""
+
+#: src/paths/instance/orders/list/Table.tsx:346
+#, c-format
+msgid "date"
+msgstr ""
+
+#: src/paths/instance/orders/list/Table.tsx:349
+#, c-format
+msgid "amount"
+msgstr ""
+
+#: src/paths/instance/orders/list/Table.tsx:352
+#, c-format
+msgid "reason"
+msgstr ""
+
+#: src/paths/instance/orders/list/Table.tsx:389
+#, c-format
+msgid "amount to be refunded"
+msgstr ""
+
+#: src/paths/instance/orders/list/Table.tsx:391
+#, c-format
+msgid "Max refundable:"
+msgstr ""
+
+#: src/paths/instance/orders/list/Table.tsx:396
+#, c-format
+msgid "Reason"
+msgstr ""
+
+#: src/paths/instance/orders/list/Table.tsx:397
+#, c-format
+msgid "Choose one..."
+msgstr ""
+
+#: src/paths/instance/orders/list/Table.tsx:399
+#, c-format
+msgid "requested by the customer"
+msgstr ""
+
+#: src/paths/instance/orders/list/Table.tsx:400
+#, c-format
+msgid "other"
+msgstr ""
+
+#: src/paths/instance/orders/list/Table.tsx:403
+#, c-format
+msgid "why this order is being refunded"
+msgstr ""
+
+#: src/paths/instance/orders/list/Table.tsx:409
+#, c-format
+msgid "more information to give context"
+msgstr ""
+
+#: src/paths/instance/orders/details/DetailPage.tsx:62
+#, c-format
+msgid "Contract Terms"
+msgstr ""
+
+#: src/paths/instance/orders/details/DetailPage.tsx:68
+#, c-format
+msgid "human-readable description of the whole purchase"
+msgstr ""
+
+#: src/paths/instance/orders/details/DetailPage.tsx:74
+#, c-format
+msgid "total price for the transaction"
+msgstr ""
+
+#: src/paths/instance/orders/details/DetailPage.tsx:81
+#, c-format
+msgid "URL for this purchase"
+msgstr ""
+
+#: src/paths/instance/orders/details/DetailPage.tsx:87
+#, c-format
+msgid "Max fee"
+msgstr ""
+
+#: src/paths/instance/orders/details/DetailPage.tsx:88
+#, c-format
+msgid "maximum total deposit fee accepted by the merchant for this contract"
+msgstr ""
+
+#: src/paths/instance/orders/details/DetailPage.tsx:93
+#, c-format
+msgid "Max wire fee"
+msgstr ""
+
+#: src/paths/instance/orders/details/DetailPage.tsx:94
+#, c-format
+msgid "maximum wire fee accepted by the merchant"
+msgstr ""
+
+#: src/paths/instance/orders/details/DetailPage.tsx:100
+#, c-format
+msgid ""
+"over how many customer transactions does the merchant expect to amortize wire 
"
+"fees on average"
+msgstr ""
+
+#: src/paths/instance/orders/details/DetailPage.tsx:105
+#, c-format
+msgid "Created at"
+msgstr ""
+
+#: src/paths/instance/orders/details/DetailPage.tsx:106
+#, c-format
+msgid "time when this contract was generated"
+msgstr ""
+
+#: src/paths/instance/orders/details/DetailPage.tsx:112
+#, c-format
+msgid "after this deadline has passed no refunds will be accepted"
+msgstr ""
+
+#: src/paths/instance/orders/details/DetailPage.tsx:118
+#, c-format
+msgid "after this deadline, the merchant won't accept payments for the 
contract"
+msgstr ""
+
+#: src/paths/instance/orders/details/DetailPage.tsx:124
+#, c-format
+msgid "transfer deadline for the exchange"
+msgstr ""
+
+#: src/paths/instance/orders/details/DetailPage.tsx:130
+#, c-format
+msgid "time indicating when the order should be delivered"
+msgstr ""
+
+#: src/paths/instance/orders/details/DetailPage.tsx:136
+#, c-format
+msgid "where the order will be delivered"
+msgstr ""
+
+#: src/paths/instance/orders/details/DetailPage.tsx:144
+#, c-format
+msgid "Auto-refund delay"
+msgstr ""
+
+#: src/paths/instance/orders/details/DetailPage.tsx:145
+#, c-format
+msgid "how long the wallet should try to get an automatic refund for the 
purchase"
+msgstr ""
+
+#: src/paths/instance/orders/details/DetailPage.tsx:150
+#, c-format
+msgid "Extra info"
+msgstr ""
+
+#: src/paths/instance/orders/details/DetailPage.tsx:151
+#, c-format
+msgid "extra data that is only interpreted by the merchant frontend"
+msgstr ""
+
+#: src/paths/instance/orders/details/DetailPage.tsx:219
+#, c-format
+msgid "Order"
+msgstr ""
+
+#: src/paths/instance/orders/details/DetailPage.tsx:221
+#, c-format
+msgid "claimed"
+msgstr ""
+
+#: src/paths/instance/orders/details/DetailPage.tsx:247
+#, c-format
+msgid "claimed at"
+msgstr ""
+
+#: src/paths/instance/orders/details/DetailPage.tsx:265
+#, c-format
+msgid "Timeline"
+msgstr ""
+
+#: src/paths/instance/orders/details/DetailPage.tsx:271
+#, c-format
+msgid "Payment details"
+msgstr ""
+
+#: src/paths/instance/orders/details/DetailPage.tsx:291
+#, c-format
+msgid "Order status"
+msgstr ""
+
+#: src/paths/instance/orders/details/DetailPage.tsx:301
+#, c-format
+msgid "Product list"
+msgstr ""
+
+#: src/paths/instance/orders/details/DetailPage.tsx:451
+#, c-format
+msgid "paid"
+msgstr ""
+
+#: src/paths/instance/orders/details/DetailPage.tsx:455
+#, c-format
+msgid "wired"
+msgstr ""
+
+#: src/paths/instance/orders/details/DetailPage.tsx:460
+#, c-format
+msgid "refunded"
+msgstr ""
+
+#: src/paths/instance/orders/details/DetailPage.tsx:480
+#, c-format
+msgid "refund order"
+msgstr ""
+
+#: src/paths/instance/orders/details/DetailPage.tsx:481
+#, c-format
+msgid "not refundable"
+msgstr ""
+
+#: src/paths/instance/orders/details/DetailPage.tsx:489
+#, c-format
+msgid "refund"
+msgstr ""
+
+#: src/paths/instance/orders/details/DetailPage.tsx:553
+#, c-format
+msgid "Refunded amount"
+msgstr ""
+
+#: src/paths/instance/orders/details/DetailPage.tsx:560
+#, c-format
+msgid "Refund taken"
+msgstr ""
+
+#: src/paths/instance/orders/details/DetailPage.tsx:570
+#, c-format
+msgid "Status URL"
+msgstr ""
+
+#: src/paths/instance/orders/details/DetailPage.tsx:583
+#, c-format
+msgid "Refund URI"
+msgstr ""
+
+#: src/paths/instance/orders/details/DetailPage.tsx:636
+#, c-format
+msgid "unpaid"
+msgstr ""
+
+#: src/paths/instance/orders/details/DetailPage.tsx:654
+#, c-format
+msgid "pay at"
+msgstr ""
+
+#: src/paths/instance/orders/details/DetailPage.tsx:666
+#, c-format
+msgid "created at"
+msgstr ""
+
+#: src/paths/instance/orders/details/DetailPage.tsx:707
+#, c-format
+msgid "Order status URL"
+msgstr ""
+
+#: src/paths/instance/orders/details/DetailPage.tsx:711
+#, c-format
+msgid "Payment URI"
+msgstr ""
+
+#: src/paths/instance/orders/details/DetailPage.tsx:740
+#, c-format
+msgid "Unknown order status. This is an error, please contact the 
administrator."
+msgstr ""
+
+#: src/paths/instance/orders/details/DetailPage.tsx:767
+#, c-format
+msgid "Back"
+msgstr ""
+
+#: src/paths/instance/orders/details/index.tsx:79
+#, c-format
+msgid "refund created successfully"
+msgstr ""
+
+#: src/paths/instance/orders/details/index.tsx:85
+#, c-format
+msgid "could not create the refund"
+msgstr ""
+
+#: src/paths/instance/orders/list/ListPage.tsx:78
+#, c-format
+msgid "select date to show nearby orders"
+msgstr ""
+
+#: src/paths/instance/orders/list/ListPage.tsx:94
+#, c-format
+msgid "order id"
+msgstr ""
+
+#: src/paths/instance/orders/list/ListPage.tsx:100
+#, c-format
+msgid "jump to order with the given order ID"
+msgstr ""
+
+#: src/paths/instance/orders/list/ListPage.tsx:122
+#, c-format
+msgid "remove all filters"
+msgstr ""
+
+#: src/paths/instance/orders/list/ListPage.tsx:132
+#, c-format
+msgid "only show paid orders"
+msgstr ""
+
+#: src/paths/instance/orders/list/ListPage.tsx:135
+#, c-format
+msgid "Paid"
+msgstr ""
+
+#: src/paths/instance/orders/list/ListPage.tsx:142
+#, c-format
+msgid "only show orders with refunds"
+msgstr ""
+
+#: src/paths/instance/orders/list/ListPage.tsx:145
+#, c-format
+msgid "Refunded"
+msgstr ""
+
+#: src/paths/instance/orders/list/ListPage.tsx:152
+#, c-format
+msgid ""
+"only show orders where customers paid, but wire payments from payment 
provider "
+"are still pending"
+msgstr ""
+
+#: src/paths/instance/orders/list/ListPage.tsx:155
+#, c-format
+msgid "Not wired"
+msgstr ""
+
+#: src/paths/instance/orders/list/ListPage.tsx:170
+#, c-format
+msgid "clear date filter"
+msgstr ""
+
+#: src/paths/instance/orders/list/ListPage.tsx:184
+#, c-format
+msgid "date (YYYY/MM/DD)"
+msgstr ""
+
+#: src/paths/instance/orders/list/index.tsx:103
+#, c-format
+msgid "Enter an order id"
+msgstr ""
+
+#: src/paths/instance/orders/list/index.tsx:111
+#, c-format
+msgid "order not found"
+msgstr ""
+
+#: src/paths/instance/orders/list/index.tsx:178
+#, c-format
+msgid "could not get the order to refund"
+msgstr ""
+
+#: src/components/exception/AsyncButton.tsx:43
+#, c-format
+msgid "Loading..."
+msgstr ""
+
+#: src/components/form/InputStock.tsx:99
+#, c-format
+msgid ""
+"click here to configure the stock of the product, leave it as is and the 
backend "
+"will not control stock"
+msgstr ""
+
+#: src/components/form/InputStock.tsx:109
+#, c-format
+msgid "Manage stock"
+msgstr ""
+
+#: src/components/form/InputStock.tsx:115
+#, c-format
+msgid "this product has been configured without stock control"
+msgstr ""
+
+#: src/components/form/InputStock.tsx:119
+#, c-format
+msgid "Infinite"
+msgstr ""
+
+#: src/components/form/InputStock.tsx:136
+#, c-format
+msgid "lost cannot be greater than current and incoming (max %1$s)"
+msgstr ""
+
+#: src/components/form/InputStock.tsx:176
+#, c-format
+msgid "Incoming"
+msgstr ""
+
+#: src/components/form/InputStock.tsx:177
+#, c-format
+msgid "Lost"
+msgstr ""
+
+#: src/components/form/InputStock.tsx:192
+#, c-format
+msgid "Current"
+msgstr ""
+
+#: src/components/form/InputStock.tsx:196
+#, c-format
+msgid "remove stock control for this product"
+msgstr ""
+
+#: src/components/form/InputStock.tsx:202
+#, c-format
+msgid "without stock"
+msgstr ""
+
+#: src/components/form/InputStock.tsx:211
+#, c-format
+msgid "Next restock"
+msgstr ""
+
+#: src/components/form/InputStock.tsx:217
+#, c-format
+msgid "Delivery address"
+msgstr ""
+
+#: src/components/product/ProductForm.tsx:133
+#, c-format
+msgid "product identification to use in URLs (for internal use only)"
+msgstr ""
+
+#: src/components/product/ProductForm.tsx:139
+#, c-format
+msgid "illustration of the product for customers"
+msgstr ""
+
+#: src/components/product/ProductForm.tsx:145
+#, c-format
+msgid "product description for customers"
+msgstr ""
+
+#: src/components/product/ProductForm.tsx:149
+#, c-format
+msgid "Age restricted"
+msgstr ""
+
+#: src/components/product/ProductForm.tsx:150
+#, c-format
+msgid "is this product restricted for customer below certain age?"
+msgstr ""
+
+#: src/components/product/ProductForm.tsx:155
+#, c-format
+msgid ""
+"unit describing quantity of product sold (e.g. 2 kilograms, 5 liters, 3 
items, 5 "
+"meters) for customers"
+msgstr ""
+
+#: src/components/product/ProductForm.tsx:160
+#, c-format
+msgid "sale price for customers, including taxes, for above units of the 
product"
+msgstr ""
+
+#: src/components/product/ProductForm.tsx:164
+#, c-format
+msgid "Stock"
+msgstr ""
+
+#: src/components/product/ProductForm.tsx:166
+#, c-format
+msgid "product inventory for products with finite supply (for internal use 
only)"
+msgstr ""
+
+#: src/components/product/ProductForm.tsx:171
+#, c-format
+msgid "taxes included in the product price, exposed to customers"
+msgstr ""
+
+#: src/paths/instance/products/create/CreatePage.tsx:66
+#, c-format
+msgid "Need to complete marked fields"
+msgstr ""
+
+#: src/paths/instance/products/create/index.tsx:51
+#, c-format
+msgid "could not create product"
+msgstr ""
+
+#: src/paths/instance/products/list/Table.tsx:68
+#, c-format
+msgid "Products"
+msgstr ""
+
+#: src/paths/instance/products/list/Table.tsx:73
+#, c-format
+msgid "add product to inventory"
+msgstr ""
+
+#: src/paths/instance/products/list/Table.tsx:137
+#, c-format
+msgid "Sell"
+msgstr ""
+
+#: src/paths/instance/products/list/Table.tsx:143
+#, c-format
+msgid "Profit"
+msgstr ""
+
+#: src/paths/instance/products/list/Table.tsx:149
+#, c-format
+msgid "Sold"
+msgstr ""
+
+#: src/paths/instance/products/list/Table.tsx:210
+#, c-format
+msgid "free"
+msgstr ""
+
+#: src/paths/instance/products/list/Table.tsx:248
+#, c-format
+msgid "go to product update page"
+msgstr ""
+
+#: src/paths/instance/products/list/Table.tsx:255
+#, c-format
+msgid "Update"
+msgstr ""
+
+#: src/paths/instance/products/list/Table.tsx:260
+#, c-format
+msgid "remove this product from the database"
+msgstr ""
+
+#: src/paths/instance/products/list/Table.tsx:331
+#, c-format
+msgid "update the product with new price"
+msgstr ""
+
+#: src/paths/instance/products/list/Table.tsx:341
+#, c-format
+msgid "update product with new price"
+msgstr ""
+
+#: src/paths/instance/products/list/Table.tsx:399
+#, c-format
+msgid "add more elements to the inventory"
+msgstr ""
+
+#: src/paths/instance/products/list/Table.tsx:404
+#, c-format
+msgid "report elements lost in the inventory"
+msgstr ""
+
+#: src/paths/instance/products/list/Table.tsx:409
+#, c-format
+msgid "new price for the product"
+msgstr ""
+
+#: src/paths/instance/products/list/Table.tsx:421
+#, c-format
+msgid "the are value with errors"
+msgstr ""
+
+#: src/paths/instance/products/list/Table.tsx:422
+#, c-format
+msgid "update product with new stock and price"
+msgstr ""
+
+#: src/paths/instance/products/list/Table.tsx:463
+#, c-format
+msgid "There is no products yet, add more pressing the + sign"
+msgstr ""
+
+#: src/paths/instance/products/list/index.tsx:86
+#, c-format
+msgid "product updated successfully"
+msgstr ""
+
+#: src/paths/instance/products/list/index.tsx:92
+#, c-format
+msgid "could not update the product"
+msgstr ""
+
+#: src/paths/instance/products/list/index.tsx:103
+#, c-format
+msgid "product delete successfully"
+msgstr ""
+
+#: src/paths/instance/products/list/index.tsx:109
+#, c-format
+msgid "could not delete the product"
+msgstr ""
+
+#: src/paths/instance/products/update/UpdatePage.tsx:56
+#, c-format
+msgid "Product id:"
+msgstr ""
+
+#: src/paths/instance/reserves/create/CreatedSuccessfully.tsx:95
+#, c-format
+msgid ""
+"To complete the setup of the reserve, you must now initiate a wire transfer "
+"using the given wire transfer subject and crediting the specified amount to 
the "
+"indicated account of the exchange."
+msgstr ""
+
+#: src/paths/instance/reserves/create/CreatedSuccessfully.tsx:102
+#, c-format
+msgid "If your system supports RFC 8905, you can do this by opening this URI:"
+msgstr ""
+
+#: src/paths/instance/reserves/create/CreatePage.tsx:83
+#, c-format
+msgid "it should be greater than 0"
+msgstr ""
+
+#: src/paths/instance/reserves/create/CreatePage.tsx:88
+#, c-format
+msgid "must be a valid URL"
+msgstr ""
+
+#: src/paths/instance/reserves/create/CreatePage.tsx:107
+#, c-format
+msgid "Initial balance"
+msgstr ""
+
+#: src/paths/instance/reserves/create/CreatePage.tsx:108
+#, c-format
+msgid "balance prior to deposit"
+msgstr ""
+
+#: src/paths/instance/reserves/create/CreatePage.tsx:112
+#, c-format
+msgid "Exchange URL"
+msgstr ""
+
+#: src/paths/instance/reserves/create/CreatePage.tsx:113
+#, c-format
+msgid "URL of exchange"
+msgstr ""
+
+#: src/paths/instance/reserves/create/CreatePage.tsx:148
+#, c-format
+msgid "Next"
+msgstr ""
+
+#: src/paths/instance/reserves/create/CreatePage.tsx:186
+#, c-format
+msgid "Wire method"
+msgstr ""
+
+#: src/paths/instance/reserves/create/CreatePage.tsx:187
+#, c-format
+msgid "method to use for wire transfer"
+msgstr ""
+
+#: src/paths/instance/reserves/create/CreatePage.tsx:189
+#, c-format
+msgid "Select one wire method"
+msgstr ""
+
+#: src/paths/instance/reserves/create/index.tsx:62
+#, c-format
+msgid "could not create reserve"
+msgstr ""
+
+#: src/paths/instance/reserves/details/DetailPage.tsx:77
+#, c-format
+msgid "Valid until"
+msgstr ""
+
+#: src/paths/instance/reserves/details/DetailPage.tsx:82
+#, c-format
+msgid "Created balance"
+msgstr ""
+
+#: src/paths/instance/reserves/details/DetailPage.tsx:99
+#, c-format
+msgid "Exchange balance"
+msgstr ""
+
+#: src/paths/instance/reserves/details/DetailPage.tsx:104
+#, c-format
+msgid "Picked up"
+msgstr ""
+
+#: src/paths/instance/reserves/details/DetailPage.tsx:109
+#, c-format
+msgid "Committed"
+msgstr ""
+
+#: src/paths/instance/reserves/details/DetailPage.tsx:116
+#, c-format
+msgid "Account address"
+msgstr ""
+
+#: src/paths/instance/reserves/details/DetailPage.tsx:119
+#, c-format
+msgid "Subject"
+msgstr ""
+
+#: src/paths/instance/reserves/details/DetailPage.tsx:130
+#, c-format
+msgid "Tips"
+msgstr ""
+
+#: src/paths/instance/reserves/details/DetailPage.tsx:193
+#, c-format
+msgid "No tips has been authorized from this reserve"
+msgstr ""
+
+#: src/paths/instance/reserves/details/DetailPage.tsx:213
+#, c-format
+msgid "Authorized"
+msgstr ""
+
+#: src/paths/instance/reserves/details/DetailPage.tsx:222
+#, c-format
+msgid "Expiration"
+msgstr ""
+
+#: src/paths/instance/reserves/list/AutorizeTipModal.tsx:108
+#, c-format
+msgid "amount of tip"
+msgstr ""
+
+#: src/paths/instance/reserves/list/AutorizeTipModal.tsx:112
+#, c-format
+msgid "Justification"
+msgstr ""
+
+#: src/paths/instance/reserves/list/AutorizeTipModal.tsx:114
+#, c-format
+msgid "reason for the tip"
+msgstr ""
+
+#: src/paths/instance/reserves/list/AutorizeTipModal.tsx:118
+#, c-format
+msgid "URL after tip"
+msgstr ""
+
+#: src/paths/instance/reserves/list/AutorizeTipModal.tsx:119
+#, c-format
+msgid "URL to visit after tip payment"
+msgstr ""
+
+#: src/paths/instance/reserves/list/Table.tsx:65
+#, c-format
+msgid "Reserves not yet funded"
+msgstr ""
+
+#: src/paths/instance/reserves/list/Table.tsx:89
+#, c-format
+msgid "Reserves ready"
+msgstr ""
+
+#: src/paths/instance/reserves/list/Table.tsx:95
+#, c-format
+msgid "add new reserve"
+msgstr ""
+
+#: src/paths/instance/reserves/list/Table.tsx:143
+#, c-format
+msgid "Expires at"
+msgstr ""
+
+#: src/paths/instance/reserves/list/Table.tsx:146
+#, c-format
+msgid "Initial"
+msgstr ""
+
+#: src/paths/instance/reserves/list/Table.tsx:202
+#, c-format
+msgid "delete selected reserve from the database"
+msgstr ""
+
+#: src/paths/instance/reserves/list/Table.tsx:210
+#, c-format
+msgid "authorize new tip from selected reserve"
+msgstr ""
+
+#: src/paths/instance/reserves/list/Table.tsx:237
+#, c-format
+msgid "There is no ready reserves yet, add more pressing the + sign or fund 
them"
+msgstr ""
+
+#: src/paths/instance/reserves/list/Table.tsx:264
+#, c-format
+msgid "Expected Balance"
+msgstr ""
+
+#: src/paths/instance/reserves/list/index.tsx:110
+#, c-format
+msgid "could not create the tip"
+msgstr ""
+
+#: src/paths/instance/templates/create/CreatePage.tsx:77
+#, c-format
+msgid "should not be empty"
+msgstr ""
+
+#: src/paths/instance/templates/create/CreatePage.tsx:93
+#, c-format
+msgid "should be greater that 0"
+msgstr ""
+
+#: src/paths/instance/templates/create/CreatePage.tsx:96
+#, c-format
+msgid "can't be empty"
+msgstr ""
+
+#: src/paths/instance/templates/create/CreatePage.tsx:100
+#, c-format
+msgid "to short"
+msgstr ""
+
+#: src/paths/instance/templates/create/CreatePage.tsx:108
+#, c-format
+msgid "just letters and numbers from 2 to 7"
+msgstr ""
+
+#: src/paths/instance/templates/create/CreatePage.tsx:110
+#, c-format
+msgid "size of the key should be 32"
+msgstr ""
+
+#: src/paths/instance/templates/create/CreatePage.tsx:137
+#, c-format
+msgid "Identifier"
+msgstr ""
+
+#: src/paths/instance/templates/create/CreatePage.tsx:138
+#, c-format
+msgid "Name of the template in URLs."
+msgstr ""
+
+#: src/paths/instance/templates/create/CreatePage.tsx:144
+#, c-format
+msgid "Describe what this template stands for"
+msgstr ""
+
+#: src/paths/instance/templates/create/CreatePage.tsx:149
+#, c-format
+msgid "Fixed summary"
+msgstr ""
+
+#: src/paths/instance/templates/create/CreatePage.tsx:150
+#, c-format
+msgid "If specified, this template will create order with the same summary"
+msgstr ""
+
+#: src/paths/instance/templates/create/CreatePage.tsx:154
+#, c-format
+msgid "Fixed price"
+msgstr ""
+
+#: src/paths/instance/templates/create/CreatePage.tsx:155
+#, c-format
+msgid "If specified, this template will create order with the same price"
+msgstr ""
+
+#: src/paths/instance/templates/create/CreatePage.tsx:159
+#, c-format
+msgid "Minimum age"
+msgstr ""
+
+#: src/paths/instance/templates/create/CreatePage.tsx:161
+#, c-format
+msgid "Is this contract restricted to some age?"
+msgstr ""
+
+#: src/paths/instance/templates/create/CreatePage.tsx:165
+#, c-format
+msgid "Payment timeout"
+msgstr ""
+
+#: src/paths/instance/templates/create/CreatePage.tsx:167
+#, c-format
+msgid ""
+"How much time has the customer to complete the payment once the order was "
+"created."
+msgstr ""
+
+#: src/paths/instance/templates/create/CreatePage.tsx:171
+#, c-format
+msgid "Verification algorithm"
+msgstr ""
+
+#: src/paths/instance/templates/create/CreatePage.tsx:172
+#, c-format
+msgid "Algorithm to use to verify transaction in offline mode"
+msgstr ""
+
+#: src/paths/instance/templates/create/CreatePage.tsx:180
+#, c-format
+msgid "Point-of-sale key"
+msgstr ""
+
+#: src/paths/instance/templates/create/CreatePage.tsx:182
+#, c-format
+msgid "Useful to validate the purchase"
+msgstr ""
+
+#: src/paths/instance/templates/create/CreatePage.tsx:196
+#, c-format
+msgid "generate random secret key"
+msgstr ""
+
+#: src/paths/instance/templates/create/CreatePage.tsx:203
+#, c-format
+msgid "random"
+msgstr ""
+
+#: src/paths/instance/templates/create/CreatePage.tsx:208
+#, c-format
+msgid "show secret key"
+msgstr ""
+
+#: src/paths/instance/templates/create/CreatePage.tsx:209
+#, c-format
+msgid "hide secret key"
+msgstr ""
+
+#: src/paths/instance/templates/create/CreatePage.tsx:216
+#, c-format
+msgid "hide"
+msgstr ""
+
+#: src/paths/instance/templates/create/CreatePage.tsx:218
+#, c-format
+msgid "show"
+msgstr ""
+
+#: src/paths/instance/templates/create/index.tsx:52
+#, c-format
+msgid "could not inform template"
+msgstr ""
+
+#: src/paths/instance/templates/use/UsePage.tsx:54
+#, c-format
+msgid "Amount is required"
+msgstr ""
+
+#: src/paths/instance/templates/use/UsePage.tsx:58
+#, c-format
+msgid "Order summary is required"
+msgstr ""
+
+#: src/paths/instance/templates/use/UsePage.tsx:86
+#, c-format
+msgid "New order for template"
+msgstr ""
+
+#: src/paths/instance/templates/use/UsePage.tsx:108
+#, c-format
+msgid "Amount of the order"
+msgstr ""
+
+#: src/paths/instance/templates/use/UsePage.tsx:113
+#, c-format
+msgid "Order summary"
+msgstr ""
+
+#: src/paths/instance/templates/use/index.tsx:92
+#, c-format
+msgid "could not create order from template"
+msgstr ""
+
+#: src/paths/instance/templates/qr/QrPage.tsx:131
+#, c-format
+msgid ""
+"Here you can specify a default value for fields that are not fixed. Default "
+"values can be edited by the customer before the payment."
+msgstr ""
+
+#: src/paths/instance/templates/qr/QrPage.tsx:148
+#, c-format
+msgid "Fixed amount"
+msgstr ""
+
+#: src/paths/instance/templates/qr/QrPage.tsx:149
+#, c-format
+msgid "Default amount"
+msgstr ""
+
+#: src/paths/instance/templates/qr/QrPage.tsx:161
+#, c-format
+msgid "Default summary"
+msgstr ""
+
+#: src/paths/instance/templates/qr/QrPage.tsx:177
+#, c-format
+msgid "Print"
+msgstr ""
+
+#: src/paths/instance/templates/qr/QrPage.tsx:184
+#, c-format
+msgid "Setup TOTP"
+msgstr ""
+
+#: src/paths/instance/templates/list/Table.tsx:65
+#, c-format
+msgid "Templates"
+msgstr ""
+
+#: src/paths/instance/templates/list/Table.tsx:70
+#, c-format
+msgid "add new templates"
+msgstr ""
+
+#: src/paths/instance/templates/list/Table.tsx:142
+#, c-format
+msgid "load more templates before the first one"
+msgstr ""
+
+#: src/paths/instance/templates/list/Table.tsx:146
+#, c-format
+msgid "load newer templates"
+msgstr ""
+
+#: src/paths/instance/templates/list/Table.tsx:181
+#, c-format
+msgid "delete selected templates from the database"
+msgstr ""
+
+#: src/paths/instance/templates/list/Table.tsx:188
+#, c-format
+msgid "use template to create new order"
+msgstr ""
+
+#: src/paths/instance/templates/list/Table.tsx:195
+#, c-format
+msgid "create qr code for the template"
+msgstr ""
+
+#: src/paths/instance/templates/list/Table.tsx:210
+#, c-format
+msgid "load more templates after the last one"
+msgstr ""
+
+#: src/paths/instance/templates/list/Table.tsx:214
+#, c-format
+msgid "load older templates"
+msgstr ""
+
+#: src/paths/instance/templates/list/Table.tsx:231
+#, c-format
+msgid "There is no templates yet, add more pressing the + sign"
+msgstr ""
+
+#: src/paths/instance/templates/list/index.tsx:104
+#, c-format
+msgid "template delete successfully"
+msgstr ""
+
+#: src/paths/instance/templates/list/index.tsx:110
+#, c-format
+msgid "could not delete the template"
+msgstr ""
+
+#: src/paths/instance/templates/update/index.tsx:90
+#, c-format
+msgid "could not update template"
+msgstr ""
+
+#: src/paths/instance/webhooks/create/CreatePage.tsx:57
+#, c-format
+msgid "should be one of '%1$s'"
+msgstr ""
+
+#: src/paths/instance/webhooks/create/CreatePage.tsx:85
+#, c-format
+msgid "Webhook ID to use"
+msgstr ""
+
+#: src/paths/instance/webhooks/create/CreatePage.tsx:89
+#, c-format
+msgid "Event"
+msgstr ""
+
+#: src/paths/instance/webhooks/create/CreatePage.tsx:90
+#, c-format
+msgid "The event of the webhook: why the webhook is used"
+msgstr ""
+
+#: src/paths/instance/webhooks/create/CreatePage.tsx:94
+#, c-format
+msgid "Method"
+msgstr ""
+
+#: src/paths/instance/webhooks/create/CreatePage.tsx:95
+#, c-format
+msgid "Method used by the webhook"
+msgstr ""
+
+#: src/paths/instance/webhooks/create/CreatePage.tsx:99
+#, c-format
+msgid "URL"
+msgstr ""
+
+#: src/paths/instance/webhooks/create/CreatePage.tsx:100
+#, c-format
+msgid "URL of the webhook where the customer will be redirected"
+msgstr ""
+
+#: src/paths/instance/webhooks/create/CreatePage.tsx:104
+#, c-format
+msgid "Header"
+msgstr ""
+
+#: src/paths/instance/webhooks/create/CreatePage.tsx:106
+#, c-format
+msgid "Header template of the webhook"
+msgstr ""
+
+#: src/paths/instance/webhooks/create/CreatePage.tsx:111
+#, c-format
+msgid "Body"
+msgstr ""
+
+#: src/paths/instance/webhooks/create/CreatePage.tsx:112
+#, c-format
+msgid "Body template by the webhook"
+msgstr ""
+
+#: src/paths/instance/webhooks/list/Table.tsx:61
+#, c-format
+msgid "Webhooks"
+msgstr ""
+
+#: src/paths/instance/webhooks/list/Table.tsx:66
+#, c-format
+msgid "add new webhooks"
+msgstr ""
+
+#: src/paths/instance/webhooks/list/Table.tsx:137
+#, c-format
+msgid "load more webhooks before the first one"
+msgstr ""
+
+#: src/paths/instance/webhooks/list/Table.tsx:141
+#, c-format
+msgid "load newer webhooks"
+msgstr ""
+
+#: src/paths/instance/webhooks/list/Table.tsx:151
+#, c-format
+msgid "Event type"
+msgstr ""
+
+#: src/paths/instance/webhooks/list/Table.tsx:176
+#, c-format
+msgid "delete selected webhook from the database"
+msgstr ""
+
+#: src/paths/instance/webhooks/list/Table.tsx:198
+#, c-format
+msgid "load more webhooks after the last one"
+msgstr ""
+
+#: src/paths/instance/webhooks/list/Table.tsx:202
+#, c-format
+msgid "load older webhooks"
+msgstr ""
+
+#: src/paths/instance/webhooks/list/Table.tsx:219
+#, c-format
+msgid "There is no webhooks yet, add more pressing the + sign"
+msgstr ""
+
+#: src/paths/instance/webhooks/list/index.tsx:94
+#, c-format
+msgid "webhook delete successfully"
+msgstr ""
+
+#: src/paths/instance/webhooks/list/index.tsx:100
+#, c-format
+msgid "could not delete the webhook"
+msgstr ""
+
+#: src/paths/instance/transfers/create/CreatePage.tsx:63
+#, c-format
+msgid "check the id, does not look valid"
+msgstr ""
+
+#: src/paths/instance/transfers/create/CreatePage.tsx:65
+#, c-format
+msgid "should have 52 characters, current %1$s"
+msgstr ""
+
+#: src/paths/instance/transfers/create/CreatePage.tsx:72
+#, c-format
+msgid "URL doesn't have the right format"
+msgstr ""
+
+#: src/paths/instance/transfers/create/CreatePage.tsx:98
+#, c-format
+msgid "Credited bank account"
+msgstr ""
+
+#: src/paths/instance/transfers/create/CreatePage.tsx:100
+#, c-format
+msgid "Select one account"
+msgstr ""
+
+#: src/paths/instance/transfers/create/CreatePage.tsx:101
+#, c-format
+msgid "Bank account of the merchant where the payment was received"
+msgstr ""
+
+#: src/paths/instance/transfers/create/CreatePage.tsx:105
+#, c-format
+msgid "Wire transfer ID"
+msgstr ""
+
+#: src/paths/instance/transfers/create/CreatePage.tsx:107
+#, c-format
+msgid ""
+"unique identifier of the wire transfer used by the exchange, must be 52 "
+"characters long"
+msgstr ""
+
+#: src/paths/instance/transfers/create/CreatePage.tsx:112
+#, c-format
+msgid ""
+"Base URL of the exchange that made the transfer, should have been in the wire 
"
+"transfer subject"
+msgstr ""
+
+#: src/paths/instance/transfers/create/CreatePage.tsx:117
+#, c-format
+msgid "Amount credited"
+msgstr ""
+
+#: src/paths/instance/transfers/create/CreatePage.tsx:118
+#, c-format
+msgid "Actual amount that was wired to the merchant's bank account"
+msgstr ""
+
+#: src/paths/instance/transfers/create/index.tsx:58
+#, c-format
+msgid "could not inform transfer"
+msgstr ""
+
+#: src/paths/instance/transfers/list/Table.tsx:61
+#, c-format
+msgid "Transfers"
+msgstr ""
+
+#: src/paths/instance/transfers/list/Table.tsx:66
+#, c-format
+msgid "add new transfer"
+msgstr ""
+
+#: src/paths/instance/transfers/list/Table.tsx:129
+#, c-format
+msgid "load more transfers before the first one"
+msgstr ""
+
+#: src/paths/instance/transfers/list/Table.tsx:133
+#, c-format
+msgid "load newer transfers"
+msgstr ""
+
+#: src/paths/instance/transfers/list/Table.tsx:143
+#, c-format
+msgid "Credit"
+msgstr ""
+
+#: src/paths/instance/transfers/list/Table.tsx:152
+#, c-format
+msgid "Confirmed"
+msgstr ""
+
+#: src/paths/instance/transfers/list/Table.tsx:155
+#, c-format
+msgid "Verified"
+msgstr ""
+
+#: src/paths/instance/transfers/list/Table.tsx:158
+#, c-format
+msgid "Executed at"
+msgstr ""
+
+#: src/paths/instance/transfers/list/Table.tsx:171
+#, c-format
+msgid "yes"
+msgstr ""
+
+#: src/paths/instance/transfers/list/Table.tsx:171
+#, c-format
+msgid "no"
+msgstr ""
+
+#: src/paths/instance/transfers/list/Table.tsx:181
+#, c-format
+msgid "unknown"
+msgstr ""
+
+#: src/paths/instance/transfers/list/Table.tsx:187
+#, c-format
+msgid "delete selected transfer from the database"
+msgstr ""
+
+#: src/paths/instance/transfers/list/Table.tsx:202
+#, c-format
+msgid "load more transfer after the last one"
+msgstr ""
+
+#: src/paths/instance/transfers/list/Table.tsx:206
+#, c-format
+msgid "load older transfers"
+msgstr ""
+
+#: src/paths/instance/transfers/list/Table.tsx:223
+#, c-format
+msgid "There is no transfer yet, add more pressing the + sign"
+msgstr ""
+
+#: src/paths/instance/transfers/list/ListPage.tsx:79
+#, c-format
+msgid "filter by account address"
+msgstr ""
+
+#: src/paths/instance/transfers/list/ListPage.tsx:100
+#, c-format
+msgid "only show wire transfers confirmed by the merchant"
+msgstr ""
+
+#: src/paths/instance/transfers/list/ListPage.tsx:110
+#, c-format
+msgid "only show wire transfers claimed by the exchange"
+msgstr ""
+
+#: src/paths/instance/transfers/list/ListPage.tsx:113
+#, c-format
+msgid "Unverified"
+msgstr ""
+
+#: src/paths/admin/create/CreatePage.tsx:69
+#, c-format
+msgid "is not valid"
+msgstr ""
+
+#: src/paths/admin/create/CreatePage.tsx:94
+#, c-format
+msgid "is not a number"
+msgstr ""
+
+#: src/paths/admin/create/CreatePage.tsx:96
+#, c-format
+msgid "must be 1 or greater"
+msgstr ""
+
+#: src/paths/admin/create/CreatePage.tsx:107
+#, c-format
+msgid "max 7 lines"
+msgstr ""
+
+#: src/paths/admin/create/CreatePage.tsx:178
+#, c-format
+msgid "change authorization configuration"
+msgstr ""
+
+#: src/paths/admin/create/CreatePage.tsx:217
+#, c-format
+msgid "Need to complete marked fields and choose authorization method"
+msgstr ""
+
+#: src/components/form/InputPaytoForm.tsx:82
+#, c-format
+msgid "This is not a valid bitcoin address."
+msgstr ""
+
+#: src/components/form/InputPaytoForm.tsx:95
+#, c-format
+msgid "This is not a valid Ethereum address."
+msgstr ""
+
+#: src/components/form/InputPaytoForm.tsx:118
+#, c-format
+msgid "IBAN numbers usually have more that 4 digits"
+msgstr ""
+
+#: src/components/form/InputPaytoForm.tsx:120
+#, c-format
+msgid "IBAN numbers usually have less that 34 digits"
+msgstr ""
+
+#: src/components/form/InputPaytoForm.tsx:128
+#, c-format
+msgid "IBAN country code not found"
+msgstr ""
+
+#: src/components/form/InputPaytoForm.tsx:153
+#, c-format
+msgid "IBAN number is not valid, checksum is wrong"
+msgstr ""
+
+#: src/components/form/InputPaytoForm.tsx:248
+#, c-format
+msgid "Target type"
+msgstr ""
+
+#: src/components/form/InputPaytoForm.tsx:249
+#, c-format
+msgid "Method to use for wire transfer"
+msgstr ""
+
+#: src/components/form/InputPaytoForm.tsx:258
+#, c-format
+msgid "Routing"
+msgstr ""
+
+#: src/components/form/InputPaytoForm.tsx:259
+#, c-format
+msgid "Routing number."
+msgstr ""
+
+#: src/components/form/InputPaytoForm.tsx:263
+#, c-format
+msgid "Account"
+msgstr ""
+
+#: src/components/form/InputPaytoForm.tsx:264
+#, c-format
+msgid "Account number."
+msgstr ""
+
+#: src/components/form/InputPaytoForm.tsx:273
+#, c-format
+msgid "Business Identifier Code."
+msgstr ""
+
+#: src/components/form/InputPaytoForm.tsx:282
+#, c-format
+msgid "Bank Account Number."
+msgstr ""
+
+#: src/components/form/InputPaytoForm.tsx:292
+#, c-format
+msgid "Unified Payment Interface."
+msgstr ""
+
+#: src/components/form/InputPaytoForm.tsx:301
+#, c-format
+msgid "Bitcoin protocol."
+msgstr ""
+
+#: src/components/form/InputPaytoForm.tsx:310
+#, c-format
+msgid "Ethereum protocol."
+msgstr ""
+
+#: src/components/form/InputPaytoForm.tsx:319
+#, c-format
+msgid "Interledger protocol."
+msgstr ""
+
+#: src/components/form/InputPaytoForm.tsx:328
+#, c-format
+msgid "Host"
+msgstr ""
+
+#: src/components/form/InputPaytoForm.tsx:329
+#, c-format
+msgid "Bank host."
+msgstr ""
+
+#: src/components/form/InputPaytoForm.tsx:334
+#, c-format
+msgid "Bank account."
+msgstr ""
+
+#: src/components/form/InputPaytoForm.tsx:343
+#, c-format
+msgid "Bank account owner's name."
+msgstr ""
+
+#: src/components/form/InputPaytoForm.tsx:370
+#, c-format
+msgid "No accounts yet."
+msgstr ""
+
+#: src/components/instance/DefaultInstanceFormFields.tsx:52
+#, c-format
+msgid ""
+"Name of the instance in URLs. The 'default' instance is special in that it is 
"
+"used to administer other instances."
+msgstr ""
+
+#: src/components/instance/DefaultInstanceFormFields.tsx:58
+#, c-format
+msgid "Business name"
+msgstr ""
+
+#: src/components/instance/DefaultInstanceFormFields.tsx:59
+#, c-format
+msgid "Legal name of the business represented by this instance."
+msgstr ""
+
+#: src/components/instance/DefaultInstanceFormFields.tsx:64
+#, c-format
+msgid "Email"
+msgstr ""
+
+#: src/components/instance/DefaultInstanceFormFields.tsx:65
+#, c-format
+msgid "Contact email"
+msgstr ""
+
+#: src/components/instance/DefaultInstanceFormFields.tsx:70
+#, c-format
+msgid "Website URL"
+msgstr ""
+
+#: src/components/instance/DefaultInstanceFormFields.tsx:71
+#, c-format
+msgid "URL."
+msgstr ""
+
+#: src/components/instance/DefaultInstanceFormFields.tsx:76
+#, c-format
+msgid "Logo"
+msgstr ""
+
+#: src/components/instance/DefaultInstanceFormFields.tsx:77
+#, c-format
+msgid "Logo image."
+msgstr ""
+
+#: src/components/instance/DefaultInstanceFormFields.tsx:82
+#, c-format
+msgid "Bank account"
+msgstr ""
+
+#: src/components/instance/DefaultInstanceFormFields.tsx:83
+#, c-format
+msgid "URI specifying bank account for crediting revenue."
+msgstr ""
+
+#: src/components/instance/DefaultInstanceFormFields.tsx:88
+#, c-format
+msgid "Default max deposit fee"
+msgstr ""
+
+#: src/components/instance/DefaultInstanceFormFields.tsx:89
+#, c-format
+msgid "Maximum deposit fees this merchant is willing to pay per order by 
default."
+msgstr ""
+
+#: src/components/instance/DefaultInstanceFormFields.tsx:94
+#, c-format
+msgid "Default max wire fee"
+msgstr ""
+
+#: src/components/instance/DefaultInstanceFormFields.tsx:95
+#, c-format
+msgid "Maximum wire fees this merchant is willing to pay per wire transfer by 
default."
+msgstr ""
+
+#: src/components/instance/DefaultInstanceFormFields.tsx:100
+#, c-format
+msgid "Default wire fee amortization"
+msgstr ""
+
+#: src/components/instance/DefaultInstanceFormFields.tsx:101
+#, c-format
+msgid ""
+"Number of orders excess wire transfer fees will be divided by to compute per "
+"order surcharge."
+msgstr ""
+
+#: src/components/instance/DefaultInstanceFormFields.tsx:107
+#, c-format
+msgid "Physical location of the merchant."
+msgstr ""
+
+#: src/components/instance/DefaultInstanceFormFields.tsx:114
+#, c-format
+msgid "Jurisdiction"
+msgstr ""
+
+#: src/components/instance/DefaultInstanceFormFields.tsx:115
+#, c-format
+msgid "Jurisdiction for legal disputes with the merchant."
+msgstr ""
+
+#: src/components/instance/DefaultInstanceFormFields.tsx:122
+#, c-format
+msgid "Default payment delay"
+msgstr ""
+
+#: src/components/instance/DefaultInstanceFormFields.tsx:124
+#, c-format
+msgid "Time customers have to pay an order before the offer expires by 
default."
+msgstr ""
+
+#: src/components/instance/DefaultInstanceFormFields.tsx:129
+#, c-format
+msgid "Default wire transfer delay"
+msgstr ""
+
+#: src/components/instance/DefaultInstanceFormFields.tsx:130
+#, c-format
+msgid ""
+"Maximum time an exchange is allowed to delay wiring funds to the merchant, "
+"enabling it to aggregate smaller payments into larger wire transfers and "
+"reducing wire fees."
+msgstr ""
+
+#: src/paths/instance/update/UpdatePage.tsx:164
+#, c-format
+msgid "Instance id"
+msgstr ""
+
+#: src/paths/instance/update/UpdatePage.tsx:173
+#, c-format
+msgid "Change the authorization method use for this instance."
+msgstr ""
+
+#: src/paths/instance/update/UpdatePage.tsx:182
+#, c-format
+msgid "Manage access token"
+msgstr ""
+
+#: src/paths/instance/update/index.tsx:112
+#, c-format
+msgid "Failed to create instance"
+msgstr ""
+
+#: src/components/exception/login.tsx:74
+#, c-format
+msgid "Login required"
+msgstr ""
+
+#: src/components/exception/login.tsx:80
+#, c-format
+msgid "Please enter your access token."
+msgstr ""
+
+#: src/components/exception/login.tsx:108
+#, c-format
+msgid "Access Token"
+msgstr ""
+
+#: src/InstanceRoutes.tsx:171
+#, c-format
+msgid "The request to the backend take too long and was cancelled"
+msgstr ""
+
+#: src/InstanceRoutes.tsx:172
+#, c-format
+msgid "Diagnostic from %1$s is \"%2$s\""
+msgstr ""
+
+#: src/InstanceRoutes.tsx:178
+#, c-format
+msgid "The backend reported a problem: HTTP status #%1$s"
+msgstr ""
+
+#: src/InstanceRoutes.tsx:179
+#, c-format
+msgid "Diagnostic from %1$s is '%2$s'"
+msgstr ""
+
+#: src/InstanceRoutes.tsx:196
+#, c-format
+msgid "Access denied"
+msgstr ""
+
+#: src/InstanceRoutes.tsx:197
+#, c-format
+msgid "The access token provided is invalid."
+msgstr ""
+
+#: src/InstanceRoutes.tsx:212
+#, c-format
+msgid "No 'default' instance configured yet."
+msgstr ""
+
+#: src/InstanceRoutes.tsx:213
+#, c-format
+msgid "Create a 'default' instance to begin using the merchant backoffice."
+msgstr ""
+
+#: src/InstanceRoutes.tsx:630
+#, c-format
+msgid "The access token provided is invalid"
+msgstr ""
+
+#: src/InstanceRoutes.tsx:664
+#, c-format
+msgid "Hide for today"
+msgstr ""
+
+#: src/components/menu/SideBar.tsx:82
+#, c-format
+msgid "Instance"
+msgstr ""
+
+#: src/components/menu/SideBar.tsx:91
+#, c-format
+msgid "Settings"
+msgstr ""
+
+#: src/components/menu/SideBar.tsx:167
+#, c-format
+msgid "Connection"
+msgstr ""
+
+#: src/components/menu/SideBar.tsx:209
+#, c-format
+msgid "New"
+msgstr ""
+
+#: src/components/menu/SideBar.tsx:219
+#, c-format
+msgid "List"
+msgstr ""
+
+#: src/components/menu/SideBar.tsx:234
+#, c-format
+msgid "Log out"
+msgstr ""
+
+#: src/ApplicationReadyRoutes.tsx:71
+#, c-format
+msgid "Check your token is valid"
+msgstr ""
+
+#: src/ApplicationReadyRoutes.tsx:90
+#, c-format
+msgid "Couldn't access the server."
+msgstr ""
+
+#: src/ApplicationReadyRoutes.tsx:91
+#, c-format
+msgid "Could not infer instance id from url %1$s"
+msgstr ""
+
+#: src/Application.tsx:104
+#, c-format
+msgid "Server not found"
+msgstr ""
+
+#: src/Application.tsx:118
+#, c-format
+msgid "Server response with an error code"
+msgstr ""
+
+#: src/Application.tsx:120
+#, c-format
+msgid "Got message %1$s from %2$s"
+msgstr ""
+
+#: src/Application.tsx:131
+#, c-format
+msgid "Response from server is unreadable, http status: %1$s"
+msgstr ""
+
+#: src/Application.tsx:144
+#, c-format
+msgid "Unexpected Error"
+msgstr ""
+
+#: src/components/form/InputArray.tsx:101
+#, c-format
+msgid "The value %1$s is invalid for a payment url"
+msgstr ""
+
+#: src/components/form/InputArray.tsx:110
+#, c-format
+msgid "add element to the list"
+msgstr ""
+
+#: src/components/form/InputArray.tsx:112
+#, c-format
+msgid "add"
+msgstr ""
+
+#: src/components/form/InputSecured.tsx:37
+#, c-format
+msgid "Deleting"
+msgstr ""
+
+#: src/components/form/InputSecured.tsx:41
+#, c-format
+msgid "Changing"
+msgstr ""
+
+#: src/paths/instance/orders/create/OrderCreatedSuccessfully.tsx:87
+#, c-format
+msgid "Order ID"
+msgstr ""
+
+#: src/paths/instance/orders/create/OrderCreatedSuccessfully.tsx:101
+#, c-format
+msgid "Payment URL"
+msgstr ""
+
diff --git a/packages/auditor-backoffice-ui/src/index.html 
b/packages/auditor-backoffice-ui/src/index.html
new file mode 100644
index 000000000..d79bdf130
--- /dev/null
+++ b/packages/auditor-backoffice-ui/src/index.html
@@ -0,0 +1,45 @@
+<!--
+ This file is part of GNU Taler
+ (C) 2021-2024 Taler Systems S.A.
+
+ GNU Taler is free software; you can redistribute it and/or modify it under the
+ terms of the GNU General Public License as published by the Free Software
+ Foundation; either version 3, or (at your option) any later version.
+
+ GNU Taler is distributed in the hope that it will be useful, but WITHOUT ANY
+ WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
+ A PARTICULAR PURPOSE.  See the GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License along with
+ GNU Taler; see the file COPYING.  If not, see <http://www.gnu.org/licenses/>
+
+ @author Sebastian Javier Marchano
+-->
+<!DOCTYPE html>
+<html
+  lang="en"
+  class="has-aside-left has-aside-mobile-transition has-navbar-fixed-top 
has-aside-expanded"
+>
+  <head>
+    <meta charset="utf-8" />
+    <meta http-equiv="content-type" content="text/html; charset=utf-8" />
+    <meta name="viewport" content="width=device-width,initial-scale=1" />
+    <meta name="mobile-web-app-capable" content="yes" />
+    <meta name="apple-mobile-web-app-capable" content="yes" />
+
+    <link
+      rel="icon"
+      
href="data:;base64,AAABAAEAEBAAAAEAIABoBAAAFgAAACgAAAAQAAAAIAAAAAEAIAAAAAAAAAQAABILAAASCwAAAAAAAAAAAAD///////////////////////////////////////////////////////////////////////////////////////////////////7//v38//78/P/+/fz//vz7///+/v/+/f3//vz7///+/v/+/fz//v38///////////////////////+/v3///7+/////////////////////////////////////////////////////////v3//v79///////+/v3///////r28v/ct5//06SG/9Gffv/Xqo7/7N/V/9e2nf/bsJb/6uDW/9Sskf/euKH/+/j2///////+/v3//////+3azv+/eE3/2rWd/9Kkhv/Vr5T/48i2/8J+VP/
 [...]
+    />
+    <link rel="shortcut icon" href="data:image/x-icon;," type="image/x-icon" />
+    <title>Auditor Backoffice</title>
+    <!-- Optional customization script.  -->
+    <script src="auditor-backoffice-ui-settings.js"></script>
+    <!-- Entry point for the demobank SPA. -->
+    <script type="module" src="index.js"></script>
+    <link rel="stylesheet" href="index.css" />
+  </head>
+  <body>
+    <div id="app"></div>
+  </body>
+</html>
diff --git a/packages/auditor-backoffice-ui/src/index.tsx 
b/packages/auditor-backoffice-ui/src/index.tsx
new file mode 100644
index 000000000..7fdf7c1c3
--- /dev/null
+++ b/packages/auditor-backoffice-ui/src/index.tsx
@@ -0,0 +1,24 @@
+/*
+ This file is part of GNU Taler
+ (C) 2021-2024 Taler Systems S.A.
+
+ GNU Taler is free software; you can redistribute it and/or modify it under the
+ terms of the GNU General Public License as published by the Free Software
+ Foundation; either version 3, or (at your option) any later version.
+
+ GNU Taler is distributed in the hope that it will be useful, but WITHOUT ANY
+ WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
+ A PARTICULAR PURPOSE.  See the GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License along with
+ GNU Taler; see the file COPYING.  If not, see <http://www.gnu.org/licenses/>
+ */
+
+import { Application } from "./Application.js";
+
+import { h, render } from "preact";
+import "./scss/main.scss";
+
+const app = document.getElementById("app");
+
+render(<Application />, app as any);
diff --git 
a/packages/auditor-backoffice-ui/src/paths/admin/create/Create.stories.tsx 
b/packages/auditor-backoffice-ui/src/paths/admin/create/Create.stories.tsx
new file mode 100644
index 000000000..91b6b4b56
--- /dev/null
+++ b/packages/auditor-backoffice-ui/src/paths/admin/create/Create.stories.tsx
@@ -0,0 +1,57 @@
+/*
+ This file is part of GNU Taler
+ (C) 2021-2023 Taler Systems S.A.
+
+ GNU Taler is free software; you can redistribute it and/or modify it under the
+ terms of the GNU General Public License as published by the Free Software
+ Foundation; either version 3, or (at your option) any later version.
+
+ GNU Taler is distributed in the hope that it will be useful, but WITHOUT ANY
+ WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
+ A PARTICULAR PURPOSE.  See the GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License along with
+ GNU Taler; see the file COPYING.  If not, see <http://www.gnu.org/licenses/>
+ */
+
+/**
+ *
+ * @author Sebastian Javier Marchano (sebasjm)
+ */
+
+import { h, VNode, FunctionalComponent } from "preact";
+import { ConfigContextProvider } from "../../../context/config.js";
+import { CreatePage as TestedComponent } from "./CreatePage.js";
+
+export default {
+  title: "Pages/Instance/Create",
+  component: TestedComponent,
+  argTypes: {
+    onCreate: { action: "onCreate" },
+    goBack: { action: "goBack" },
+  },
+};
+
+function createExample<Props>(
+  Component: FunctionalComponent<Props>,
+  props: Partial<Props>,
+) {
+  const r = (args: any) => (
+    <ConfigContextProvider
+      value={{
+        currency: "ARS",
+        version: "1",
+      }}
+    >
+      <Component {...args} />
+    </ConfigContextProvider>
+  );
+  r.args = props;
+  return r;
+}
+
+export const Example = createExample(TestedComponent, {});
+// export const Example = (a: any): VNode => <CreatePage {...a} />;
+// Example.args = {
+//   isLoading: false
+// }
diff --git 
a/packages/auditor-backoffice-ui/src/paths/admin/create/CreatePage.tsx 
b/packages/auditor-backoffice-ui/src/paths/admin/create/CreatePage.tsx
new file mode 100644
index 000000000..d13b7e929
--- /dev/null
+++ b/packages/auditor-backoffice-ui/src/paths/admin/create/CreatePage.tsx
@@ -0,0 +1,257 @@
+/*
+ This file is part of GNU Taler
+ (C) 2021-2023 Taler Systems S.A.
+
+ GNU Taler is free software; you can redistribute it and/or modify it under the
+ terms of the GNU General Public License as published by the Free Software
+ Foundation; either version 3, or (at your option) any later version.
+
+ GNU Taler is distributed in the hope that it will be useful, but WITHOUT ANY
+ WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
+ A PARTICULAR PURPOSE.  See the GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License along with
+ GNU Taler; see the file COPYING.  If not, see <http://www.gnu.org/licenses/>
+ */
+
+/**
+ *
+ * @author Sebastian Javier Marchano (sebasjm)
+ */
+
+import { useTranslationContext } from "@gnu-taler/web-util/browser";
+import { h, VNode } from "preact";
+import { useState } from "preact/hooks";
+import { AsyncButton } from "../../../components/exception/AsyncButton.js";
+import {
+  FormErrors,
+  FormProvider,
+} from "../../../components/form/FormProvider.js";
+import { DefaultInstanceFormFields } from 
"../../../components/instance/DefaultInstanceFormFields.js";
+import { MerchantBackend } from "../../../declaration.js";
+import { INSTANCE_ID_REGEX } from "../../../utils/constants.js";
+import { undefinedIfEmpty } from "../../../utils/table.js";
+import { SetTokenNewInstanceModal } from "../../../components/modal/index.js";
+import { Duration } from "@gnu-taler/taler-util";
+
+export type Entity = 
Omit<Omit<MerchantBackend.Instances.InstanceConfigurationMessage, 
"default_pay_delay">, "default_wire_transfer_delay"> & {
+  auth_token?: string;
+  default_pay_delay: Duration,
+  default_wire_transfer_delay: Duration,
+};
+
+interface Props {
+  onCreate: (d: MerchantBackend.Instances.InstanceConfigurationMessage) => 
Promise<void>;
+  onBack?: () => void;
+  forceId?: string;
+}
+
+function with_defaults(id?: string): Partial<Entity> {
+  return {
+    id,
+    // accounts: [],
+    user_type: "business",
+    use_stefan: true,
+    default_pay_delay: { d_ms: 2 * 60 * 60 * 1000 }, // two hours
+    default_wire_transfer_delay: { d_ms: 2 * 60 * 60 * 24 * 1000 }, // two days
+  };
+}
+
+export function CreatePage({ onCreate, onBack, forceId }: Props): VNode {
+  const [value, valueHandler] = useState(with_defaults(forceId));
+  const [isTokenSet, updateIsTokenSet] = useState<boolean>(false);
+  const [isTokenDialogActive, updateIsTokenDialogActive] =
+    useState<boolean>(false);
+
+  const { i18n } = useTranslationContext();
+
+  const errors: FormErrors<Entity> = {
+    id: !value.id
+      ? i18n.str`required`
+      : !INSTANCE_ID_REGEX.test(value.id)
+        ? i18n.str`is not valid`
+        : undefined,
+    name: !value.name ? i18n.str`required` : undefined,
+
+    user_type: !value.user_type
+      ? i18n.str`required`
+      : value.user_type !== "business" && value.user_type !== "individual"
+        ? i18n.str`should be business or individual`
+        : undefined,
+    // accounts:
+    //   !value.accounts || !value.accounts.length
+    //     ? i18n.str`required`
+    //     : undefinedIfEmpty(
+    //       value.accounts.map((p) => {
+    //         return !PAYTO_REGEX.test(p.payto_uri)
+    //           ? i18n.str`is not valid`
+    //           : undefined;
+    //       }),
+    //     ),
+    default_pay_delay: !value.default_pay_delay
+      ? i18n.str`required`
+      : !!value.default_wire_transfer_delay &&
+        value.default_wire_transfer_delay.d_ms !== "forever" &&
+        value.default_pay_delay.d_ms !== "forever" &&
+        value.default_pay_delay.d_ms > value.default_wire_transfer_delay.d_ms ?
+        i18n.str`pay delay can't be greater than wire transfer delay` : 
undefined,
+    default_wire_transfer_delay: !value.default_wire_transfer_delay
+      ? i18n.str`required`
+      : undefined,
+    address: undefinedIfEmpty({
+      address_lines:
+        value.address?.address_lines && value.address?.address_lines.length > 7
+          ? i18n.str`max 7 lines`
+          : undefined,
+    }),
+    jurisdiction: undefinedIfEmpty({
+      address_lines:
+        value.address?.address_lines && value.address?.address_lines.length > 7
+          ? i18n.str`max 7 lines`
+          : undefined,
+    }),
+  };
+
+  const hasErrors = Object.keys(errors).some(
+    (k) => (errors as any)[k] !== undefined,
+  );
+
+  const submit = (): Promise<void> => {
+    // use conversion instead of this
+    const newToken = value.auth_token;
+    value.auth_token = undefined;
+    value.auth = newToken === null || newToken === undefined
+      ? { method: "external" }
+      : { method: "token", token: `secret-token:${newToken}` };
+    if (!value.address) value.address = {};
+    if (!value.jurisdiction) value.jurisdiction = {};
+    // remove above use conversion
+    // schema.validateSync(value, { abortEarly: false })
+    value.default_pay_delay = 
Duration.toTalerProtocolDuration(value.default_pay_delay!) as any
+    value.default_wire_transfer_delay = 
Duration.toTalerProtocolDuration(value.default_wire_transfer_delay!) as any
+    // delete value.default_pay_delay;
+    // delete value.default_wire_transfer_delay;
+
+    return onCreate(value as any as 
MerchantBackend.Instances.InstanceConfigurationMessage);
+  };
+
+  function updateToken(token: string | null) {
+    valueHandler((old) => ({
+      ...old,
+      auth_token: token === null ? undefined : token,
+    }));
+  }
+
+  return (
+    <div>
+      <div class="columns">
+        <div class="column" />
+        <div class="column is-four-fifths">
+          {isTokenDialogActive && (
+            <SetTokenNewInstanceModal
+              onCancel={() => {
+                updateIsTokenDialogActive(false);
+                updateIsTokenSet(false);
+              }}
+              onClear={() => {
+                updateToken(null);
+                updateIsTokenDialogActive(false);
+                updateIsTokenSet(true);
+              }}
+              onConfirm={(newToken) => {
+                updateToken(newToken);
+                updateIsTokenDialogActive(false);
+                updateIsTokenSet(true);
+              }}
+            />
+          )}
+        </div>
+        <div class="column" />
+      </div>
+
+      <section class="section is-main-section">
+        <div class="columns">
+          <div class="column" />
+          <div class="column is-four-fifths">
+            <FormProvider<Entity>
+              errors={errors}
+              object={value}
+              valueHandler={valueHandler}
+            >
+              <DefaultInstanceFormFields readonlyId={!!forceId} showId={true} 
/>
+            </FormProvider>
+
+            <div class="level">
+              <div class="level-item has-text-centered">
+                <h1 class="title">
+                  <button
+                    class={
+                      !isTokenSet
+                        ? "button is-danger has-tooltip-bottom"
+                        : !value.auth_token
+                          ? "button has-tooltip-bottom"
+                          : "button is-info has-tooltip-bottom"
+                    }
+                    data-tooltip={i18n.str`change authorization configuration`}
+                    onClick={() => updateIsTokenDialogActive(true)}
+                  >
+                    <div class="icon is-centered">
+                      <i class="mdi mdi-lock-reset" />
+                    </div>
+                    <span>
+                      <i18n.Translate>Set access token</i18n.Translate>
+                    </span>
+                  </button>
+                </h1>
+              </div>
+            </div>
+            <div class="level">
+              <div class="level-item has-text-centered">
+                {!isTokenSet ? (
+                  <p class="is-size-6">
+                    <i18n.Translate>
+                      Access token is not yet configured. This instance can't 
be
+                      created.
+                    </i18n.Translate>
+                  </p>
+                ) : value.auth_token === undefined ? (
+                  <p class="is-size-6">
+                    <i18n.Translate>
+                      No access token. Authorization must be handled 
externally.
+                    </i18n.Translate>
+                  </p>
+                ) : (
+                  <p class="is-size-6">
+                    <i18n.Translate>
+                      Access token is set. Authorization is handled by the
+                      merchant backend.
+                    </i18n.Translate>
+                  </p>
+                )}
+              </div>
+            </div>
+            <div class="buttons is-right mt-5">
+              {onBack && (
+                <button class="button" onClick={onBack}>
+                  <i18n.Translate>Cancel</i18n.Translate>
+                </button>
+              )}
+              <AsyncButton
+                onClick={submit}
+                disabled={hasErrors || !isTokenSet}
+                data-tooltip={
+                  hasErrors
+                    ? i18n.str`Need to complete marked fields and choose 
authorization method`
+                    : "confirm operation"
+                }
+              >
+                <i18n.Translate>Confirm</i18n.Translate>
+              </AsyncButton>
+            </div>
+          </div>
+          <div class="column" />
+        </div>
+      </section>
+    </div>
+  );
+}
diff --git 
a/packages/auditor-backoffice-ui/src/paths/admin/create/InstanceCreatedSuccessfully.tsx
 
b/packages/auditor-backoffice-ui/src/paths/admin/create/InstanceCreatedSuccessfully.tsx
new file mode 100644
index 000000000..c620c6482
--- /dev/null
+++ 
b/packages/auditor-backoffice-ui/src/paths/admin/create/InstanceCreatedSuccessfully.tsx
@@ -0,0 +1,74 @@
+/*
+ This file is part of GNU Taler
+ (C) 2021-2023 Taler Systems S.A.
+
+ GNU Taler is free software; you can redistribute it and/or modify it under the
+ terms of the GNU General Public License as published by the Free Software
+ Foundation; either version 3, or (at your option) any later version.
+
+ GNU Taler is distributed in the hope that it will be useful, but WITHOUT ANY
+ WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
+ A PARTICULAR PURPOSE.  See the GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License along with
+ GNU Taler; see the file COPYING.  If not, see <http://www.gnu.org/licenses/>
+ */
+/**
+ *
+ * @author Sebastian Javier Marchano (sebasjm)
+ */
+import { h, VNode } from "preact";
+import { CreatedSuccessfully } from 
"../../../components/notifications/CreatedSuccessfully.js";
+import { Entity } from "./index.js";
+
+export function InstanceCreatedSuccessfully({
+  entity,
+  onConfirm,
+}: {
+  entity: Entity;
+  onConfirm: () => void;
+}): VNode {
+  return (
+    <CreatedSuccessfully onConfirm={onConfirm}>
+      <div class="field is-horizontal">
+        <div class="field-label is-normal">
+          <label class="label">ID</label>
+        </div>
+        <div class="field-body is-flex-grow-3">
+          <div class="field">
+            <p class="control">
+              <input class="input" readonly value={entity.id} />
+            </p>
+          </div>
+        </div>
+      </div>
+      <div class="field is-horizontal">
+        <div class="field-label is-normal">
+          <label class="label">Business Name</label>
+        </div>
+        <div class="field-body is-flex-grow-3">
+          <div class="field">
+            <p class="control">
+              <input class="input" readonly value={entity.name} />
+            </p>
+          </div>
+        </div>
+      </div>
+      <div class="field is-horizontal">
+        <div class="field-label is-normal">
+          <label class="label">Access token</label>
+        </div>
+        <div class="field-body is-flex-grow-3">
+          <div class="field">
+            <p class="control">
+              {entity.auth.method === "external" && "external"}
+              {entity.auth.method === "token" && (
+                <input class="input" readonly value={entity.auth.token} />
+              )}
+            </p>
+          </div>
+        </div>
+      </div>
+    </CreatedSuccessfully>
+  );
+}
diff --git a/packages/auditor-backoffice-ui/src/paths/admin/create/index.tsx 
b/packages/auditor-backoffice-ui/src/paths/admin/create/index.tsx
new file mode 100644
index 000000000..23f41ecff
--- /dev/null
+++ b/packages/auditor-backoffice-ui/src/paths/admin/create/index.tsx
@@ -0,0 +1,82 @@
+/*
+ This file is part of GNU Taler
+ (C) 2021-2023 Taler Systems S.A.
+
+ GNU Taler is free software; you can redistribute it and/or modify it under the
+ terms of the GNU General Public License as published by the Free Software
+ Foundation; either version 3, or (at your option) any later version.
+
+ GNU Taler is distributed in the hope that it will be useful, but WITHOUT ANY
+ WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
+ A PARTICULAR PURPOSE.  See the GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License along with
+ GNU Taler; see the file COPYING.  If not, see <http://www.gnu.org/licenses/>
+ */
+/**
+ *
+ * @author Sebastian Javier Marchano (sebasjm)
+ */
+import { useTranslationContext } from "@gnu-taler/web-util/browser";
+import { Fragment, h, VNode } from "preact";
+import { useState } from "preact/hooks";
+import { NotificationCard } from "../../../components/menu/index.js";
+import { AccessToken, MerchantBackend } from "../../../declaration.js";
+import { useAdminAPI, useInstanceAPI } from "../../../hooks/instance.js";
+import { Notification } from "../../../utils/types.js";
+import { CreatePage } from "./CreatePage.js";
+import { useCredentialsChecker } from "../../../hooks/backend.js";
+import { useBackendContext } from "../../../context/backend.js";
+
+interface Props {
+  onBack?: () => void;
+  onConfirm: () => void;
+  forceId?: string;
+}
+export type Entity = MerchantBackend.Instances.InstanceConfigurationMessage;
+
+export default function Create({ onBack, onConfirm, forceId }: Props): VNode {
+  const { createInstance } = useAdminAPI();
+  const [notif, setNotif] = useState<Notification | undefined>(undefined);
+  const { i18n } = useTranslationContext();
+  const { requestNewLoginToken } = useCredentialsChecker()
+  const { url: backendURL, updateToken } = useBackendContext()
+
+  return (
+    <Fragment>
+      <NotificationCard notification={notif} />
+
+      <CreatePage
+        onBack={onBack}
+        forceId={forceId}
+        onCreate={async (
+          d: MerchantBackend.Instances.InstanceConfigurationMessage,
+        ) => {
+          try {
+            await createInstance(d)
+            if (d.auth.token) {
+              const resp = await requestNewLoginToken(backendURL, d.auth.token 
as AccessToken)
+              if (resp.valid) {
+                const { token, expiration } = resp
+                updateToken({ token, expiration });
+              } else {
+                updateToken(undefined)
+              }
+                      }
+            onConfirm();
+          } catch (ex) {
+            if (ex instanceof Error) {
+              setNotif({
+                message: i18n.str`Failed to create instance`,
+                type: "ERROR",
+                description: ex.message,
+              });
+            } else {
+              console.error(ex)
+            }
+          }
+        }}
+      />
+    </Fragment>
+  );
+}
diff --git a/packages/auditor-backoffice-ui/src/paths/admin/create/stories.tsx 
b/packages/auditor-backoffice-ui/src/paths/admin/create/stories.tsx
new file mode 100644
index 000000000..0012f9b9b
--- /dev/null
+++ b/packages/auditor-backoffice-ui/src/paths/admin/create/stories.tsx
@@ -0,0 +1,52 @@
+/*
+ This file is part of GNU Taler
+ (C) 2021-2023 Taler Systems S.A.
+
+ GNU Taler is free software; you can redistribute it and/or modify it under the
+ terms of the GNU General Public License as published by the Free Software
+ Foundation; either version 3, or (at your option) any later version.
+
+ GNU Taler is distributed in the hope that it will be useful, but WITHOUT ANY
+ WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
+ A PARTICULAR PURPOSE.  See the GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License along with
+ GNU Taler; see the file COPYING.  If not, see <http://www.gnu.org/licenses/>
+ */
+
+/**
+ *
+ * @author Sebastian Javier Marchano (sebasjm)
+ */
+
+import { h, VNode, FunctionalComponent } from "preact";
+import { ConfigContextProvider } from "../../../context/config.js";
+import { CreatePage as TestedComponent } from "./CreatePage.js";
+
+export default {
+  title: "Pages/Instance/Create",
+  component: TestedComponent,
+  argTypes: {
+    onCreate: { action: "onCreate" },
+    goBack: { action: "goBack" },
+  },
+};
+
+function createExample<Props>(
+  Internal: FunctionalComponent<Props>,
+  props: Partial<Props>,
+) {
+  const component = (args: any) => (
+    <ConfigContextProvider
+      value={{
+        currency: "TESTKUDOS",
+        version: "1",
+      }}
+    >
+      <Internal {...(props as any)} />
+    </ConfigContextProvider>
+  );
+  return { component, props };
+}
+
+export const Example = createExample(TestedComponent, {});
diff --git a/packages/auditor-backoffice-ui/src/paths/admin/index.stories.ts 
b/packages/auditor-backoffice-ui/src/paths/admin/index.stories.ts
new file mode 100644
index 000000000..fdae1a24d
--- /dev/null
+++ b/packages/auditor-backoffice-ui/src/paths/admin/index.stories.ts
@@ -0,0 +1,18 @@
+/*
+ This file is part of GNU Taler
+ (C) 2021-2023 Taler Systems S.A.
+
+ GNU Taler is free software; you can redistribute it and/or modify it under the
+ terms of the GNU General Public License as published by the Free Software
+ Foundation; either version 3, or (at your option) any later version.
+
+ GNU Taler is distributed in the hope that it will be useful, but WITHOUT ANY
+ WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
+ A PARTICULAR PURPOSE.  See the GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License along with
+ GNU Taler; see the file COPYING.  If not, see <http://www.gnu.org/licenses/>
+ */
+
+// export * as list from "./list/stories.js";
+export * as create from "./create/stories.js";
diff --git 
a/packages/auditor-backoffice-ui/src/paths/admin/list/TableActive.tsx 
b/packages/auditor-backoffice-ui/src/paths/admin/list/TableActive.tsx
new file mode 100644
index 000000000..885a351d2
--- /dev/null
+++ b/packages/auditor-backoffice-ui/src/paths/admin/list/TableActive.tsx
@@ -0,0 +1,287 @@
+/*
+ This file is part of GNU Taler
+ (C) 2021-2023 Taler Systems S.A.
+
+ GNU Taler is free software; you can redistribute it and/or modify it under the
+ terms of the GNU General Public License as published by the Free Software
+ Foundation; either version 3, or (at your option) any later version.
+
+ GNU Taler is distributed in the hope that it will be useful, but WITHOUT ANY
+ WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
+ A PARTICULAR PURPOSE.  See the GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License along with
+ GNU Taler; see the file COPYING.  If not, see <http://www.gnu.org/licenses/>
+ */
+
+/**
+ *
+ * @author Sebastian Javier Marchano (sebasjm)
+ */
+
+import { useTranslationContext } from "@gnu-taler/web-util/browser";
+import { h, VNode } from "preact";
+import { StateUpdater, useEffect, useState } from "preact/hooks";
+import { MerchantBackend } from "../../../declaration.js";
+
+interface Props {
+  instances: MerchantBackend.Instances.Instance[];
+  onUpdate: (id: string) => void;
+  onDelete: (id: MerchantBackend.Instances.Instance) => void;
+  onPurge: (id: MerchantBackend.Instances.Instance) => void;
+  onCreate: () => void;
+  selected?: boolean;
+  setInstanceName: (s: string) => void;
+}
+
+export function CardTable({
+  instances,
+  onCreate,
+  onUpdate,
+  onPurge,
+  setInstanceName,
+  onDelete,
+  selected,
+}: Props): VNode {
+  const [actionQueue, actionQueueHandler] = useState<Actions[]>([]);
+  const [rowSelection, rowSelectionHandler] = useState<string[]>([]);
+
+  useEffect(() => {
+    if (
+      actionQueue.length > 0 &&
+      !selected &&
+      actionQueue[0].type == "DELETE"
+    ) {
+      onDelete(actionQueue[0].element);
+      actionQueueHandler(actionQueue.slice(1));
+    }
+  }, [actionQueue, selected, onDelete]);
+
+  useEffect(() => {
+    if (
+      actionQueue.length > 0 &&
+      !selected &&
+      actionQueue[0].type == "UPDATE"
+    ) {
+      onUpdate(actionQueue[0].element.id);
+      actionQueueHandler(actionQueue.slice(1));
+    }
+  }, [actionQueue, selected, onUpdate]);
+
+  const { i18n } = useTranslationContext();
+
+  return (
+    <div class="card has-table">
+      <header class="card-header">
+        <p class="card-header-title">
+          <span class="icon">
+            <i class="mdi mdi-desktop-mac" />
+          </span>
+          <i18n.Translate>Instances</i18n.Translate>
+        </p>
+
+        <div class="card-header-icon" aria-label="more options">
+          <button
+            class={rowSelection.length > 0 ? "button is-danger" : "is-hidden"}
+            type="button"
+            onClick={(): void =>
+              actionQueueHandler(
+                buildActions(instances, rowSelection, "DELETE"),
+              )
+            }
+          >
+            <i18n.Translate>Delete</i18n.Translate>
+          </button>
+        </div>
+        <div class="card-header-icon" aria-label="more options">
+          <span
+            class="has-tooltip-left"
+            data-tooltip={i18n.str`add new instance`}
+          >
+            <button class="button is-info" type="button" onClick={onCreate}>
+              <span class="icon is-small">
+                <i class="mdi mdi-plus mdi-36px" />
+              </span>
+            </button>
+          </span>
+        </div>
+      </header>
+      <div class="card-content">
+        <div class="b-table has-pagination">
+          <div class="table-wrapper has-mobile-cards">
+            {instances.length > 0 ? (
+              <Table
+                instances={instances}
+                onPurge={onPurge}
+                onUpdate={onUpdate}
+                setInstanceName={setInstanceName}
+                onDelete={onDelete}
+                rowSelection={rowSelection}
+                rowSelectionHandler={rowSelectionHandler}
+              />
+            ) : (
+              <EmptyTable />
+            )}
+          </div>
+        </div>
+      </div>
+    </div>
+  );
+}
+interface TableProps {
+  rowSelection: string[];
+  instances: MerchantBackend.Instances.Instance[];
+  onUpdate: (id: string) => void;
+  onDelete: (id: MerchantBackend.Instances.Instance) => void;
+  onPurge: (id: MerchantBackend.Instances.Instance) => void;
+  rowSelectionHandler: StateUpdater<string[]>;
+  setInstanceName: (s: string) => void;
+}
+
+function toggleSelected<T>(id: T): (prev: T[]) => T[] {
+  return (prev: T[]): T[] =>
+    prev.indexOf(id) == -1 ? [...prev, id] : prev.filter((e) => e != id);
+}
+
+function Table({
+  rowSelection,
+  rowSelectionHandler,
+  setInstanceName,
+  instances,
+  onUpdate,
+  onDelete,
+  onPurge,
+}: TableProps): VNode {
+  const { i18n } = useTranslationContext();
+  return (
+    <div class="table-container">
+      <table class="table is-fullwidth is-striped is-hoverable is-fullwidth">
+        <thead>
+          <tr>
+            <th class="is-checkbox-cell">
+              <label class="b-checkbox checkbox">
+                <input
+                  type="checkbox"
+                  checked={rowSelection.length === instances.length}
+                  onClick={(): void =>
+                    rowSelectionHandler(
+                      rowSelection.length === instances.length
+                        ? []
+                        : instances.map((i) => i.id),
+                    )
+                  }
+                />
+                <span class="check" />
+              </label>
+            </th>
+            <th>
+              <i18n.Translate>ID</i18n.Translate>
+            </th>
+            <th>
+              <i18n.Translate>Name</i18n.Translate>
+            </th>
+            <th />
+          </tr>
+        </thead>
+        <tbody>
+          {instances.map((i) => {
+            return (
+              <tr key={i.id}>
+                <td class="is-checkbox-cell">
+                  <label class="b-checkbox checkbox">
+                    <input
+                      type="checkbox"
+                      checked={rowSelection.indexOf(i.id) != -1}
+                      onClick={(): void =>
+                        rowSelectionHandler(toggleSelected(i.id))
+                      }
+                    />
+                    <span class="check" />
+                  </label>
+                </td>
+                <td>
+                  <a
+                    href={`#/orders?instance=${i.id}`}
+                    onClick={(e) => {
+                      setInstanceName(i.id);
+                    }}
+                  >
+                    {i.id}
+                  </a>
+                </td>
+                <td>{i.name}</td>
+                <td class="is-actions-cell right-sticky">
+                  <div class="buttons is-right">
+                    <button
+                      class="button is-small is-success jb-modal"
+                      type="button"
+                      onClick={(): void => onUpdate(i.id)}
+                    >
+                      <i18n.Translate>Edit</i18n.Translate>
+                    </button>
+                    {!i.deleted && (
+                      <button
+                        class="button is-small is-danger jb-modal is-outlined"
+                        type="button"
+                        onClick={(): void => onDelete(i)}
+                      >
+                        <i18n.Translate>Delete</i18n.Translate>
+                      </button>
+                    )}
+                    {i.deleted && (
+                      <button
+                        class="button is-small is-danger jb-modal"
+                        type="button"
+                        onClick={(): void => onPurge(i)}
+                      >
+                        <i18n.Translate>Purge</i18n.Translate>
+                      </button>
+                    )}
+                  </div>
+                </td>
+              </tr>
+            );
+          })}
+        </tbody>
+      </table>
+    </div>
+  );
+}
+
+function EmptyTable(): VNode {
+  const { i18n } = useTranslationContext();
+  return (
+    <div class="content has-text-grey has-text-centered">
+      <p>
+        <span class="icon is-large">
+          <i class="mdi mdi-emoticon-sad mdi-48px" />
+        </span>
+      </p>
+      <p>
+        <i18n.Translate>
+          There is no instances yet, add more pressing the + sign
+        </i18n.Translate>
+      </p>
+    </div>
+  );
+}
+
+interface Actions {
+  element: MerchantBackend.Instances.Instance;
+  type: "DELETE" | "UPDATE";
+}
+
+function notEmpty<TValue>(value: TValue | null | undefined): value is TValue {
+  return value !== null && value !== undefined;
+}
+
+function buildActions(
+  instances: MerchantBackend.Instances.Instance[],
+  selected: string[],
+  action: "DELETE",
+): Actions[] {
+  return selected
+    .map((id) => instances.find((i) => i.id === id))
+    .filter(notEmpty)
+    .map((id) => ({ element: id, type: action }));
+}
diff --git 
a/packages/auditor-backoffice-ui/src/paths/admin/list/View.stories.tsx 
b/packages/auditor-backoffice-ui/src/paths/admin/list/View.stories.tsx
new file mode 100644
index 000000000..e0f5d5430
--- /dev/null
+++ b/packages/auditor-backoffice-ui/src/paths/admin/list/View.stories.tsx
@@ -0,0 +1,90 @@
+/*
+ This file is part of GNU Taler
+ (C) 2021-2023 Taler Systems S.A.
+
+ GNU Taler is free software; you can redistribute it and/or modify it under the
+ terms of the GNU General Public License as published by the Free Software
+ Foundation; either version 3, or (at your option) any later version.
+
+ GNU Taler is distributed in the hope that it will be useful, but WITHOUT ANY
+ WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
+ A PARTICULAR PURPOSE.  See the GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License along with
+ GNU Taler; see the file COPYING.  If not, see <http://www.gnu.org/licenses/>
+ */
+
+/**
+ *
+ * @author Sebastian Javier Marchano (sebasjm)
+ */
+
+import { h } from "preact";
+import { View } from "./View.js";
+
+export default {
+  title: "Pages/Instance/List",
+  component: View,
+  argTypes: {
+    onSelect: { action: "onSelect" },
+  },
+};
+
+export const Empty = (a: any) => <View {...a} />;
+Empty.args = {
+  instances: [],
+};
+
+export const WithDefaultInstance = (a: any) => <View {...a} />;
+WithDefaultInstance.args = {
+  instances: [
+    {
+      id: "default",
+      name: "the default instance",
+      merchant_pub: "abcdef",
+      payment_targets: [],
+    },
+  ],
+};
+
+export const WithFiveInstance = (a: any) => <View {...a} />;
+WithFiveInstance.args = {
+  instances: [
+    {
+      id: "first",
+      name: "the first instance",
+      merchant_pub: "abcdefgh",
+      payment_targets: ["asd"],
+    },
+    {
+      id: "second",
+      name: "the second instance",
+      merchant_pub: "zxczxcz",
+      payment_targets: ["asd"],
+    },
+    {
+      id: "third",
+      name: "the third instance",
+      merchant_pub: "QWEQWEWQE",
+      payment_targets: ["asd"],
+    },
+    {
+      id: "other",
+      name: "the other instance",
+      merchant_pub: "FHJHGJGHJ",
+      payment_targets: ["asd"],
+    },
+    {
+      id: "another",
+      name: "the another instance",
+      merchant_pub: "abcd3423423efgh",
+      payment_targets: ["asd"],
+    },
+    {
+      id: "last",
+      name: "last instance",
+      merchant_pub: "zxcvvbnm",
+      payment_targets: ["pay-to", "asd"],
+    },
+  ],
+};
diff --git a/packages/auditor-backoffice-ui/src/paths/admin/list/View.tsx 
b/packages/auditor-backoffice-ui/src/paths/admin/list/View.tsx
new file mode 100644
index 000000000..b59112338
--- /dev/null
+++ b/packages/auditor-backoffice-ui/src/paths/admin/list/View.tsx
@@ -0,0 +1,110 @@
+/*
+ This file is part of GNU Taler
+ (C) 2021-2023 Taler Systems S.A.
+
+ GNU Taler is free software; you can redistribute it and/or modify it under the
+ terms of the GNU General Public License as published by the Free Software
+ Foundation; either version 3, or (at your option) any later version.
+
+ GNU Taler is distributed in the hope that it will be useful, but WITHOUT ANY
+ WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
+ A PARTICULAR PURPOSE.  See the GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License along with
+ GNU Taler; see the file COPYING.  If not, see <http://www.gnu.org/licenses/>
+ */
+
+/**
+ *
+ * @author Sebastian Javier Marchano (sebasjm)
+ */
+
+import { useTranslationContext } from "@gnu-taler/web-util/browser";
+import { h, VNode } from "preact";
+import { useState } from "preact/hooks";
+import { MerchantBackend } from "../../../declaration.js";
+import { CardTable as CardTableActive } from "./TableActive.js";
+
+interface Props {
+  instances: MerchantBackend.Instances.Instance[];
+  onCreate: () => void;
+  onUpdate: (id: string) => void;
+  onDelete: (id: MerchantBackend.Instances.Instance) => void;
+  onPurge: (id: MerchantBackend.Instances.Instance) => void;
+  selected?: boolean;
+  setInstanceName: (s: string) => void;
+}
+
+export function View({
+  instances,
+  onCreate,
+  onDelete,
+  onPurge,
+  onUpdate,
+  setInstanceName,
+  selected,
+}: Props): VNode {
+  const [show, setShow] = useState<"active" | "deleted" | null>("active");
+  const showIsActive = show === "active" ? "is-active" : "";
+  const showIsDeleted = show === "deleted" ? "is-active" : "";
+  const showAll = show === null ? "is-active" : "";
+  const { i18n } = useTranslationContext();
+
+  const showingInstances = showIsDeleted
+    ? instances.filter((i) => i.deleted)
+    : showIsActive
+    ? instances.filter((i) => !i.deleted)
+    : instances;
+
+  return (
+    <section class="section is-main-section">
+      <div class="columns">
+        <div class="column is-two-thirds">
+          <div class="tabs" style={{ overflow: "inherit" }}>
+            <ul>
+              <li class={showIsActive}>
+                <div
+                  class="has-tooltip-right"
+                  data-tooltip={i18n.str`Only show active instances`}
+                >
+                  <a onClick={() => setShow("active")}>
+                    <i18n.Translate>Active</i18n.Translate>
+                  </a>
+                </div>
+              </li>
+              <li class={showIsDeleted}>
+                <div
+                  class="has-tooltip-right"
+                  data-tooltip={i18n.str`Only show deleted instances`}
+                >
+                  <a onClick={() => setShow("deleted")}>
+                    <i18n.Translate>Deleted</i18n.Translate>
+                  </a>
+                </div>
+              </li>
+              <li class={showAll}>
+                <div
+                  class="has-tooltip-right"
+                  data-tooltip={i18n.str`Show all instances`}
+                >
+                  <a onClick={() => setShow(null)}>
+                    <i18n.Translate>All</i18n.Translate>
+                  </a>
+                </div>
+              </li>
+            </ul>
+          </div>
+        </div>
+      </div>
+      <CardTableActive
+        instances={showingInstances}
+        onDelete={onDelete}
+        onPurge={onPurge}
+        setInstanceName={setInstanceName}
+        onUpdate={onUpdate}
+        selected={selected}
+        onCreate={onCreate}
+      />
+    </section>
+  );
+}
diff --git a/packages/auditor-backoffice-ui/src/paths/admin/list/index.tsx 
b/packages/auditor-backoffice-ui/src/paths/admin/list/index.tsx
new file mode 100644
index 000000000..2f839291b
--- /dev/null
+++ b/packages/auditor-backoffice-ui/src/paths/admin/list/index.tsx
@@ -0,0 +1,140 @@
+/*
+ This file is part of GNU Taler
+ (C) 2021-2023 Taler Systems S.A.
+
+ GNU Taler is free software; you can redistribute it and/or modify it under the
+ terms of the GNU General Public License as published by the Free Software
+ Foundation; either version 3, or (at your option) any later version.
+
+ GNU Taler is distributed in the hope that it will be useful, but WITHOUT ANY
+ WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
+ A PARTICULAR PURPOSE.  See the GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License along with
+ GNU Taler; see the file COPYING.  If not, see <http://www.gnu.org/licenses/>
+ */
+
+/**
+ *
+ * @author Sebastian Javier Marchano (sebasjm)
+ */
+
+import {
+  ErrorType,
+  HttpError,
+  useTranslationContext,
+} from "@gnu-taler/web-util/browser";
+import { Fragment, h, VNode } from "preact";
+import { useState } from "preact/hooks";
+import { Loading } from "../../../components/exception/loading.js";
+import { NotificationCard } from "../../../components/menu/index.js";
+import { DeleteModal, PurgeModal } from "../../../components/modal/index.js";
+import { MerchantBackend } from "../../../declaration.js";
+import { useAdminAPI, useBackendInstances } from "../../../hooks/instance.js";
+import { Notification } from "../../../utils/types.js";
+import { View } from "./View.js";
+import { HttpStatusCode } from "@gnu-taler/taler-util";
+
+interface Props {
+  onCreate: () => void;
+  onUpdate: (id: string) => void;
+  instances: MerchantBackend.Instances.Instance[];
+  onUnauthorized: () => VNode;
+  onNotFound: () => VNode;
+  onLoadError: (error: HttpError<MerchantBackend.ErrorDetail>) => VNode;
+  setInstanceName: (s: string) => void;
+}
+
+export default function Instances({
+  onUnauthorized,
+  onLoadError,
+  onNotFound,
+  onCreate,
+  onUpdate,
+  setInstanceName,
+}: Props): VNode {
+  const result = useBackendInstances();
+  const [deleting, setDeleting] =
+    useState<MerchantBackend.Instances.Instance | null>(null);
+  const [purging, setPurging] =
+    useState<MerchantBackend.Instances.Instance | null>(null);
+  const { deleteInstance, purgeInstance } = useAdminAPI();
+  const [notif, setNotif] = useState<Notification | undefined>(undefined);
+  const { i18n } = useTranslationContext();
+
+  if (result.loading) return <Loading />;
+  if (!result.ok) {
+    if (
+      result.type === ErrorType.CLIENT &&
+      result.status === HttpStatusCode.Unauthorized
+    )
+      return onUnauthorized();
+    if (
+      result.type === ErrorType.CLIENT &&
+      result.status === HttpStatusCode.NotFound
+    )
+      return onNotFound();
+    return onLoadError(result);
+  }
+
+  return (
+    <Fragment>
+      <NotificationCard notification={notif} />
+      <View
+        instances={result.data.instances}
+        onDelete={setDeleting}
+        onCreate={onCreate}
+        onPurge={setPurging}
+        onUpdate={onUpdate}
+        setInstanceName={setInstanceName}
+        selected={!!deleting}
+      />
+      {deleting && (
+        <DeleteModal
+          element={deleting}
+          onCancel={() => setDeleting(null)}
+          onConfirm={async (): Promise<void> => {
+            try {
+              await deleteInstance(deleting.id);
+              // pushNotification({ message: 'delete_success', type: 'SUCCESS' 
})
+              setNotif({
+                message: i18n.str`Instance "${deleting.name}" (ID: 
${deleting.id}) has been deleted`,
+                type: "SUCCESS",
+              });
+            } catch (error) {
+              setNotif({
+                message: i18n.str`Failed to delete instance`,
+                type: "ERROR",
+                description: error instanceof Error ? error.message : 
undefined,
+              });
+              // pushNotification({ message: 'delete_error', type: 'ERROR' })
+            }
+            setDeleting(null);
+          }}
+        />
+      )}
+      {purging && (
+        <PurgeModal
+          element={purging}
+          onCancel={() => setPurging(null)}
+          onConfirm={async (): Promise<void> => {
+            try {
+              await purgeInstance(purging.id);
+              setNotif({
+                message: i18n.str`Instance '${purging.name}' (ID: 
${purging.id}) has been disabled`,
+                type: "SUCCESS",
+              });
+            } catch (error) {
+              setNotif({
+                message: i18n.str`Failed to purge instance`,
+                type: "ERROR",
+                description: error instanceof Error ? error.message : 
undefined,
+              });
+            }
+            setPurging(null);
+          }}
+        />
+      )}
+    </Fragment>
+  );
+}
diff --git 
a/packages/auditor-backoffice-ui/src/paths/instance/accounts/create/Create.stories.tsx
 
b/packages/auditor-backoffice-ui/src/paths/instance/accounts/create/Create.stories.tsx
new file mode 100644
index 000000000..3336c53a4
--- /dev/null
+++ 
b/packages/auditor-backoffice-ui/src/paths/instance/accounts/create/Create.stories.tsx
@@ -0,0 +1,28 @@
+/*
+ This file is part of GNU Taler
+ (C) 2021-2023 Taler Systems S.A.
+
+ GNU Taler is free software; you can redistribute it and/or modify it under the
+ terms of the GNU General Public License as published by the Free Software
+ Foundation; either version 3, or (at your option) any later version.
+
+ GNU Taler is distributed in the hope that it will be useful, but WITHOUT ANY
+ WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
+ A PARTICULAR PURPOSE.  See the GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License along with
+ GNU Taler; see the file COPYING.  If not, see <http://www.gnu.org/licenses/>
+ */
+
+/**
+ *
+ * @author Sebastian Javier Marchano (sebasjm)
+ */
+
+import { h, VNode, FunctionalComponent } from "preact";
+import { CreatePage as TestedComponent } from "./CreatePage.js";
+
+export default {
+  title: "Pages/Accounts/Create",
+  component: TestedComponent,
+};
diff --git 
a/packages/auditor-backoffice-ui/src/paths/instance/accounts/create/CreatePage.tsx
 
b/packages/auditor-backoffice-ui/src/paths/instance/accounts/create/CreatePage.tsx
new file mode 100644
index 000000000..6e4786a47
--- /dev/null
+++ 
b/packages/auditor-backoffice-ui/src/paths/instance/accounts/create/CreatePage.tsx
@@ -0,0 +1,173 @@
+/*
+ This file is part of GNU Taler
+ (C) 2021-2023 Taler Systems S.A.
+
+ GNU Taler is free software; you can redistribute it and/or modify it under the
+ terms of the GNU General Public License as published by the Free Software
+ Foundation; either version 3, or (at your option) any later version.
+
+ GNU Taler is distributed in the hope that it will be useful, but WITHOUT ANY
+ WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
+ A PARTICULAR PURPOSE.  See the GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License along with
+ GNU Taler; see the file COPYING.  If not, see <http://www.gnu.org/licenses/>
+ */
+
+/**
+ *
+ * @author Sebastian Javier Marchano (sebasjm)
+ */
+
+import { useTranslationContext } from "@gnu-taler/web-util/browser";
+import { Fragment, h, VNode } from "preact";
+import { useState } from "preact/hooks";
+import { AsyncButton } from "../../../../components/exception/AsyncButton.js";
+import {
+  FormErrors,
+  FormProvider,
+} from "../../../../components/form/FormProvider.js";
+import { Input } from "../../../../components/form/Input.js";
+import { InputPaytoForm } from "../../../../components/form/InputPaytoForm.js";
+import { InputSelector } from "../../../../components/form/InputSelector.js";
+import { MerchantBackend } from "../../../../declaration.js";
+import { undefinedIfEmpty } from "../../../../utils/table.js";
+
+type Entity = MerchantBackend.BankAccounts.AccountAddDetails & { 
repeatPassword: string };
+
+interface Props {
+  onCreate: (d: Entity) => Promise<void>;
+  onBack?: () => void;
+}
+
+const accountAuthType = ["none", "basic"];
+
+function isValidURL(s: string): boolean {
+  try {
+    const u = new URL(s)
+    return true;
+  } catch (e) {
+    return false;
+  }
+}
+
+export function CreatePage({ onCreate, onBack }: Props): VNode {
+  const { i18n } = useTranslationContext();
+
+  const [state, setState] = useState<Partial<Entity>>({});
+  const errors: FormErrors<Entity> = {
+    payto_uri: !state.payto_uri ? i18n.str`required` : undefined,
+
+    credit_facade_credentials: !state.credit_facade_credentials
+      ? undefined
+      : undefinedIfEmpty({
+        username:
+          state.credit_facade_credentials.type === "basic" && 
!state.credit_facade_credentials.username
+            ? i18n.str`required`
+            : undefined,
+        password:
+          state.credit_facade_credentials.type === "basic" && 
!state.credit_facade_credentials.password
+            ? i18n.str`required`
+            : undefined,
+      }),
+    credit_facade_url: !state.credit_facade_url
+      ? undefined
+      : !isValidURL(state.credit_facade_url) ? i18n.str`not valid url`
+        : undefined,
+    repeatPassword:
+      !state.credit_facade_credentials
+        ? undefined
+        : state.credit_facade_credentials.type === "basic" && 
(!state.credit_facade_credentials.password || 
state.credit_facade_credentials.password !== state.repeatPassword)
+          ? i18n.str`is not the same`
+          : undefined,
+  };
+
+  const hasErrors = Object.keys(errors).some(
+    (k) => (errors as any)[k] !== undefined,
+  );
+
+  const submitForm = () => {
+    if (hasErrors) return Promise.reject();
+    delete state.repeatPassword
+    return onCreate(state as any);
+  };
+
+  return (
+    <div>
+      <section class="section is-main-section">
+        <div class="columns">
+          <div class="column" />
+          <div class="column is-four-fifths">
+            <FormProvider
+              object={state}
+              valueHandler={setState}
+              errors={errors}
+            >
+              <InputPaytoForm<Entity>
+                name="payto_uri"
+                label={i18n.str`Account`}
+              />
+              <Input<Entity>
+                name="credit_facade_url"
+                label={i18n.str`Account info URL`}
+                help="https://bank.com";
+                expand
+                tooltip={i18n.str`From where the merchant can download 
information about incoming wire transfers to this account`}
+              />
+              <InputSelector
+                name="credit_facade_credentials.type"
+                label={i18n.str`Auth type`}
+                tooltip={i18n.str`Choose the authentication type for the 
account info URL`}
+                values={accountAuthType}
+                toStr={(str) => {
+                  if (str === "none") return "Without authentication";
+                  return "Username and password";
+                }}
+              />
+              {state.credit_facade_credentials?.type === "basic" ? (
+                <Fragment>
+                  <Input
+                    name="credit_facade_credentials.username"
+                    label={i18n.str`Username`}
+                    tooltip={i18n.str`Username to access the account 
information.`}
+                  />
+                  <Input
+                    name="credit_facade_credentials.password"
+                    inputType="password"
+                    label={i18n.str`Password`}
+                    tooltip={i18n.str`Password to access the account 
information.`}
+                  />
+                  <Input
+                    name="repeatPassword"
+                    inputType="password"
+                    label={i18n.str`Repeat password`}
+                  />
+                </Fragment>
+              ) : undefined}
+            </FormProvider>
+
+            <div class="buttons is-right mt-5">
+              {onBack && (
+                <button class="button" onClick={onBack}>
+                  <i18n.Translate>Cancel</i18n.Translate>
+                </button>
+              )}
+              <AsyncButton
+                disabled={hasErrors}
+                data-tooltip={
+                  hasErrors
+                    ? i18n.str`Need to complete marked fields`
+                    : "confirm operation"
+                }
+                onClick={submitForm}
+              >
+                <i18n.Translate>Confirm</i18n.Translate>
+              </AsyncButton>
+            </div>
+          </div>
+          <div class="column" />
+        </div>
+      </section>
+    </div>
+  );
+}
diff --git 
a/packages/auditor-backoffice-ui/src/paths/instance/accounts/create/index.tsx 
b/packages/auditor-backoffice-ui/src/paths/instance/accounts/create/index.tsx
new file mode 100644
index 000000000..7d33d25ce
--- /dev/null
+++ 
b/packages/auditor-backoffice-ui/src/paths/instance/accounts/create/index.tsx
@@ -0,0 +1,65 @@
+/*
+ This file is part of GNU Taler
+ (C) 2021-2023 Taler Systems S.A.
+
+ GNU Taler is free software; you can redistribute it and/or modify it under the
+ terms of the GNU General Public License as published by the Free Software
+ Foundation; either version 3, or (at your option) any later version.
+
+ GNU Taler is distributed in the hope that it will be useful, but WITHOUT ANY
+ WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
+ A PARTICULAR PURPOSE.  See the GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License along with
+ GNU Taler; see the file COPYING.  If not, see <http://www.gnu.org/licenses/>
+ */
+
+/**
+ *
+ * @author Sebastian Javier Marchano (sebasjm)
+ */
+
+import { useTranslationContext } from "@gnu-taler/web-util/browser";
+import { Fragment, h, VNode } from "preact";
+import { useState } from "preact/hooks";
+import { NotificationCard } from "../../../../components/menu/index.js";
+import { MerchantBackend } from "../../../../declaration.js";
+import { useWebhookAPI } from "../../../../hooks/webhooks.js";
+import { Notification } from "../../../../utils/types.js";
+import { CreatePage } from "./CreatePage.js";
+import { useOtpDeviceAPI } from "../../../../hooks/otp.js";
+import { useBankAccountAPI } from "../../../../hooks/bank.js";
+
+export type Entity = MerchantBackend.BankAccounts.AccountAddDetails;
+interface Props {
+  onBack?: () => void;
+  onConfirm: () => void;
+}
+
+export default function CreateValidator({ onConfirm, onBack }: Props): VNode {
+  const { createBankAccount } = useBankAccountAPI();
+  const [notif, setNotif] = useState<Notification | undefined>(undefined);
+  const { i18n } = useTranslationContext();
+
+  return (
+    <>
+      <NotificationCard notification={notif} />
+      <CreatePage
+        onBack={onBack}
+        onCreate={(request: Entity) => {
+          return createBankAccount(request)
+            .then((d) => {
+              onConfirm()
+            })
+            .catch((error) => {
+              setNotif({
+                message: i18n.str`could not create device`,
+                type: "ERROR",
+                description: error.message,
+              });
+            });
+        }}
+      />
+    </>
+  );
+}
diff --git 
a/packages/auditor-backoffice-ui/src/paths/instance/accounts/list/List.stories.tsx
 
b/packages/auditor-backoffice-ui/src/paths/instance/accounts/list/List.stories.tsx
new file mode 100644
index 000000000..6b4b63735
--- /dev/null
+++ 
b/packages/auditor-backoffice-ui/src/paths/instance/accounts/list/List.stories.tsx
@@ -0,0 +1,28 @@
+/*
+ This file is part of GNU Taler
+ (C) 2021-2023 Taler Systems S.A.
+
+ GNU Taler is free software; you can redistribute it and/or modify it under the
+ terms of the GNU General Public License as published by the Free Software
+ Foundation; either version 3, or (at your option) any later version.
+
+ GNU Taler is distributed in the hope that it will be useful, but WITHOUT ANY
+ WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
+ A PARTICULAR PURPOSE.  See the GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License along with
+ GNU Taler; see the file COPYING.  If not, see <http://www.gnu.org/licenses/>
+ */
+
+/**
+ *
+ * @author Sebastian Javier Marchano (sebasjm)
+ */
+
+import { FunctionalComponent, h } from "preact";
+import { ListPage as TestedComponent } from "./ListPage.js";
+
+export default {
+  title: "Pages/Accounts/List",
+  component: TestedComponent,
+};
diff --git 
a/packages/auditor-backoffice-ui/src/paths/instance/accounts/list/ListPage.tsx 
b/packages/auditor-backoffice-ui/src/paths/instance/accounts/list/ListPage.tsx
new file mode 100644
index 000000000..24da755b9
--- /dev/null
+++ 
b/packages/auditor-backoffice-ui/src/paths/instance/accounts/list/ListPage.tsx
@@ -0,0 +1,64 @@
+/*
+ This file is part of GNU Taler
+ (C) 2021-2023 Taler Systems S.A.
+
+ GNU Taler is free software; you can redistribute it and/or modify it under the
+ terms of the GNU General Public License as published by the Free Software
+ Foundation; either version 3, or (at your option) any later version.
+
+ GNU Taler is distributed in the hope that it will be useful, but WITHOUT ANY
+ WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
+ A PARTICULAR PURPOSE.  See the GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License along with
+ GNU Taler; see the file COPYING.  If not, see <http://www.gnu.org/licenses/>
+ */
+
+/**
+ *
+ * @author Sebastian Javier Marchano (sebasjm)
+ */
+
+import { h, VNode } from "preact";
+import { MerchantBackend } from "../../../../declaration.js";
+import { useTranslationContext } from "@gnu-taler/web-util/browser";
+import { CardTable } from "./Table.js";
+
+export interface Props {
+  devices: MerchantBackend.BankAccounts.BankAccountEntry[];
+  onLoadMoreBefore?: () => void;
+  onLoadMoreAfter?: () => void;
+  onCreate: () => void;
+  onDelete: (e: MerchantBackend.BankAccounts.BankAccountEntry) => void;
+  onSelect: (e: MerchantBackend.BankAccounts.BankAccountEntry) => void;
+}
+
+export function ListPage({
+  devices,
+  onCreate,
+  onDelete,
+  onSelect,
+  onLoadMoreBefore,
+  onLoadMoreAfter,
+}: Props): VNode {
+  const form = { payto_uri: "" };
+
+  const { i18n } = useTranslationContext();
+  return (
+    <section class="section is-main-section">
+      <CardTable
+        accounts={devices.map((o) => ({
+          ...o,
+          id: String(o.h_wire),
+        }))}
+        onCreate={onCreate}
+        onDelete={onDelete}
+        onSelect={onSelect}
+        onLoadMoreBefore={onLoadMoreBefore}
+        hasMoreBefore={!onLoadMoreBefore}
+        onLoadMoreAfter={onLoadMoreAfter}
+        hasMoreAfter={!onLoadMoreAfter}
+      />
+    </section>
+  );
+}
diff --git 
a/packages/auditor-backoffice-ui/src/paths/instance/accounts/list/Table.tsx 
b/packages/auditor-backoffice-ui/src/paths/instance/accounts/list/Table.tsx
new file mode 100644
index 000000000..7d6db0782
--- /dev/null
+++ b/packages/auditor-backoffice-ui/src/paths/instance/accounts/list/Table.tsx
@@ -0,0 +1,385 @@
+/*
+ This file is part of GNU Taler
+ (C) 2021-2023 Taler Systems S.A.
+
+ GNU Taler is free software; you can redistribute it and/or modify it under the
+ terms of the GNU General Public License as published by the Free Software
+ Foundation; either version 3, or (at your option) any later version.
+
+ GNU Taler is distributed in the hope that it will be useful, but WITHOUT ANY
+ WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
+ A PARTICULAR PURPOSE.  See the GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License along with
+ GNU Taler; see the file COPYING.  If not, see <http://www.gnu.org/licenses/>
+ */
+
+/**
+ *
+ * @author Sebastian Javier Marchano (sebasjm)
+ */
+
+import { useTranslationContext } from "@gnu-taler/web-util/browser";
+import { Fragment, h, VNode } from "preact";
+import { StateUpdater, useState } from "preact/hooks";
+import { MerchantBackend } from "../../../../declaration.js";
+import { parsePaytoUri, PaytoType, PaytoUri, PaytoUriBitcoin, PaytoUriIBAN, 
PaytoUriTalerBank, PaytoUriUnknown } from "@gnu-taler/taler-util";
+
+type Entity = MerchantBackend.BankAccounts.BankAccountEntry;
+
+interface Props {
+  accounts: Entity[];
+  onDelete: (e: Entity) => void;
+  onSelect: (e: Entity) => void;
+  onCreate: () => void;
+  onLoadMoreBefore?: () => void;
+  hasMoreBefore?: boolean;
+  hasMoreAfter?: boolean;
+  onLoadMoreAfter?: () => void;
+}
+
+export function CardTable({
+  accounts,
+  onCreate,
+  onDelete,
+  onSelect,
+  onLoadMoreAfter,
+  onLoadMoreBefore,
+  hasMoreAfter,
+  hasMoreBefore,
+}: Props): VNode {
+  const [rowSelection, rowSelectionHandler] = useState<string[]>([]);
+
+  const { i18n } = useTranslationContext();
+
+  return (
+    <div class="card has-table">
+      <header class="card-header">
+        <p class="card-header-title">
+          <span class="icon">
+            <i class="mdi mdi-newspaper" />
+          </span>
+          <i18n.Translate>Bank accounts</i18n.Translate>
+        </p>
+        <div class="card-header-icon" aria-label="more options">
+          <span
+            class="has-tooltip-left"
+            data-tooltip={i18n.str`add new accounts`}
+          >
+            <button class="button is-info" type="button" onClick={onCreate}>
+              <span class="icon is-small">
+                <i class="mdi mdi-plus mdi-36px" />
+              </span>
+            </button>
+          </span>
+        </div>
+      </header>
+      <div class="card-content">
+        <div class="b-table has-pagination">
+          <div class="table-wrapper has-mobile-cards">
+            {accounts.length > 0 ? (
+              <Table
+                accounts={accounts}
+                onDelete={onDelete}
+                onSelect={onSelect}
+                rowSelection={rowSelection}
+                rowSelectionHandler={rowSelectionHandler}
+                onLoadMoreAfter={onLoadMoreAfter}
+                onLoadMoreBefore={onLoadMoreBefore}
+                hasMoreAfter={hasMoreAfter}
+                hasMoreBefore={hasMoreBefore}
+              />
+            ) : (
+              <EmptyTable />
+            )}
+          </div>
+        </div>
+      </div>
+    </div>
+  );
+}
+interface TableProps {
+  rowSelection: string[];
+  accounts: Entity[];
+  onDelete: (e: Entity) => void;
+  onSelect: (e: Entity) => void;
+  rowSelectionHandler: StateUpdater<string[]>;
+  onLoadMoreBefore?: () => void;
+  hasMoreBefore?: boolean;
+  hasMoreAfter?: boolean;
+  onLoadMoreAfter?: () => void;
+}
+
+function toggleSelected<T>(id: T): (prev: T[]) => T[] {
+  return (prev: T[]): T[] =>
+    prev.indexOf(id) == -1 ? [...prev, id] : prev.filter((e) => e != id);
+}
+
+function Table({
+  accounts,
+  onLoadMoreAfter,
+  onDelete,
+  onSelect,
+  onLoadMoreBefore,
+  hasMoreAfter,
+  hasMoreBefore,
+}: TableProps): VNode {
+  const { i18n } = useTranslationContext();
+  const emptyList: Record<PaytoType | "unknown", { parsed: PaytoUri, acc: 
Entity }[]> = { "bitcoin": [], "x-taler-bank": [], "iban": [], "unknown": [], }
+  const accountsByType = accounts.reduce((prev, acc) => {
+    const parsed = parsePaytoUri(acc.payto_uri)
+    if (!parsed) return prev //skip
+    if (parsed.targetType !== "bitcoin" && parsed.targetType !== 
"x-taler-bank" && parsed.targetType !== "iban") {
+      prev["unknown"].push({ parsed, acc })
+    } else {
+      prev[parsed.targetType].push({ parsed, acc })
+    }
+    return prev
+  }, emptyList)
+
+  const bitcoinAccounts = accountsByType["bitcoin"]
+  const talerbankAccounts = accountsByType["x-taler-bank"]
+  const ibanAccounts = accountsByType["iban"]
+  const unkownAccounts = accountsByType["unknown"]
+
+
+  return (
+    <Fragment>
+
+      {bitcoinAccounts.length > 0 && <div class="table-container">
+        <p class="card-header-title"><i18n.Translate>Bitcoin type 
accounts</i18n.Translate></p>
+        <table class="table is-fullwidth is-striped is-hoverable is-fullwidth">
+          <thead>
+            <tr>
+              <th>
+                <i18n.Translate>Address</i18n.Translate>
+              </th>
+              <th>
+                <i18n.Translate>Sewgit 1</i18n.Translate>
+              </th>
+              <th>
+                <i18n.Translate>Sewgit 2</i18n.Translate>
+              </th>
+              <th />
+            </tr>
+          </thead>
+          <tbody>
+            {bitcoinAccounts.map(({ parsed, acc }, idx) => {
+              const ac = parsed as PaytoUriBitcoin
+              return (
+                <tr key={idx}>
+                  <td
+                    onClick={(): void => onSelect(acc)}
+                    style={{ cursor: "pointer" }}
+                  >
+                    {ac.targetPath}
+                  </td>
+                  <td
+                    onClick={(): void => onSelect(acc)}
+                    style={{ cursor: "pointer" }}
+                  >
+                    {ac.segwitAddrs[0]}
+                  </td>
+                  <td
+                    onClick={(): void => onSelect(acc)}
+                    style={{ cursor: "pointer" }}
+                  >
+                    {ac.segwitAddrs[1]}
+                  </td>
+                  <td class="is-actions-cell right-sticky">
+                    <div class="buttons is-right">
+                      <button
+                        class="button is-danger is-small has-tooltip-left"
+                        data-tooltip={i18n.str`delete selected accounts from 
the database`}
+                        onClick={() => onDelete(acc)}
+                      >
+                        Delete
+                      </button>
+                    </div>
+                  </td>
+                </tr>
+              );
+            })}
+          </tbody>
+        </table>
+      </div>}
+
+
+
+      {talerbankAccounts.length > 0 && <div class="table-container">
+        <p class="card-header-title"><i18n.Translate>Taler type 
accounts</i18n.Translate></p>
+        <table class="table is-fullwidth is-striped is-hoverable is-fullwidth">
+          <thead>
+            <tr>
+              <th>
+                <i18n.Translate>Host</i18n.Translate>
+              </th>
+              <th>
+                <i18n.Translate>Account name</i18n.Translate>
+              </th>
+              <th />
+            </tr>
+          </thead>
+          <tbody>
+            {talerbankAccounts.map(({ parsed, acc }, idx) => {
+              const ac = parsed as PaytoUriTalerBank
+              return (
+                <tr key={idx}>
+                  <td
+                    onClick={(): void => onSelect(acc)}
+                    style={{ cursor: "pointer" }}
+                  >
+                    {ac.host}
+                  </td>
+                  <td
+                    onClick={(): void => onSelect(acc)}
+                    style={{ cursor: "pointer" }}
+                  >
+                    {ac.account}
+                  </td>
+                  <td class="is-actions-cell right-sticky">
+                    <div class="buttons is-right">
+                      <button
+                        class="button is-danger is-small has-tooltip-left"
+                        data-tooltip={i18n.str`delete selected accounts from 
the database`}
+                        onClick={() => onDelete(acc)}
+                      >
+                        Delete
+                      </button>
+                    </div>
+                  </td>
+                </tr>
+              );
+            })}
+          </tbody>
+        </table>
+      </div>}
+
+      {ibanAccounts.length > 0 && <div class="table-container">
+        <p class="card-header-title"><i18n.Translate>IBAN type 
accounts</i18n.Translate></p>
+        <table class="table is-fullwidth is-striped is-hoverable is-fullwidth">
+          <thead>
+            <tr>
+              <th>
+                <i18n.Translate>Account name</i18n.Translate>
+              </th>
+              <th>
+                <i18n.Translate>IBAN</i18n.Translate>
+              </th>
+              <th>
+                <i18n.Translate>BIC</i18n.Translate>
+              </th>
+              <th />
+            </tr>
+          </thead>
+          <tbody>
+            {ibanAccounts.map(({ parsed, acc }, idx) => {
+              const ac = parsed as PaytoUriIBAN
+              return (
+                <tr key={idx}>
+                  <td
+                    onClick={(): void => onSelect(acc)}
+                    style={{ cursor: "pointer" }}
+                  >
+                    {ac.params["receiver-name"]}
+                  </td>
+                  <td
+                    onClick={(): void => onSelect(acc)}
+                    style={{ cursor: "pointer" }}
+                  >
+                    {ac.iban}
+                  </td>
+                  <td
+                    onClick={(): void => onSelect(acc)}
+                    style={{ cursor: "pointer" }}
+                  >
+                    {ac.bic ?? ""}
+                  </td>
+                  <td class="is-actions-cell right-sticky">
+                    <div class="buttons is-right">
+                      <button
+                        class="button is-danger is-small has-tooltip-left"
+                        data-tooltip={i18n.str`delete selected accounts from 
the database`}
+                        onClick={() => onDelete(acc)}
+                      >
+                        Delete
+                      </button>
+                    </div>
+                  </td>
+                </tr>
+              );
+            })}
+          </tbody>
+        </table>
+      </div>}
+
+      {unkownAccounts.length > 0 && <div class="table-container">
+        <p class="card-header-title"><i18n.Translate>Other type 
accounts</i18n.Translate></p>
+        <table class="table is-fullwidth is-striped is-hoverable is-fullwidth">
+          <thead>
+            <tr>
+              <th>
+                <i18n.Translate>Type</i18n.Translate>
+              </th>
+              <th>
+                <i18n.Translate>Path</i18n.Translate>
+              </th>
+              <th />
+            </tr>
+          </thead>
+          <tbody>
+            {unkownAccounts.map(({ parsed, acc }, idx) => {
+              const ac = parsed as PaytoUriUnknown
+              return (
+                <tr key={idx}>
+                  <td
+                    onClick={(): void => onSelect(acc)}
+                    style={{ cursor: "pointer" }}
+                  >
+                    {ac.targetType}
+                  </td>
+                  <td
+                    onClick={(): void => onSelect(acc)}
+                    style={{ cursor: "pointer" }}
+                  >
+                    {ac.targetPath}
+                  </td>
+                  <td class="is-actions-cell right-sticky">
+                    <div class="buttons is-right">
+                      <button
+                        class="button is-danger is-small has-tooltip-left"
+                        data-tooltip={i18n.str`delete selected accounts from 
the database`}
+                        onClick={() => onDelete(acc)}
+                      >
+                        Delete
+                      </button>
+                    </div>
+                  </td>
+                </tr>
+              );
+            })}
+          </tbody>
+        </table>
+      </div>}
+    </Fragment>
+
+  );
+}
+
+function EmptyTable(): VNode {
+  const { i18n } = useTranslationContext();
+  return (
+    <div class="content has-text-grey has-text-centered">
+      <p>
+        <span class="icon is-large">
+          <i class="mdi mdi-emoticon-sad mdi-48px" />
+        </span>
+      </p>
+      <p>
+        <i18n.Translate>
+          There is no accounts yet, add more pressing the + sign
+        </i18n.Translate>
+      </p>
+    </div>
+  );
+}
diff --git 
a/packages/auditor-backoffice-ui/src/paths/instance/accounts/list/index.tsx 
b/packages/auditor-backoffice-ui/src/paths/instance/accounts/list/index.tsx
new file mode 100644
index 000000000..100241e22
--- /dev/null
+++ b/packages/auditor-backoffice-ui/src/paths/instance/accounts/list/index.tsx
@@ -0,0 +1,107 @@
+/*
+ This file is part of GNU Taler
+ (C) 2021-2023 Taler Systems S.A.
+
+ GNU Taler is free software; you can redistribute it and/or modify it under the
+ terms of the GNU General Public License as published by the Free Software
+ Foundation; either version 3, or (at your option) any later version.
+
+ GNU Taler is distributed in the hope that it will be useful, but WITHOUT ANY
+ WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
+ A PARTICULAR PURPOSE.  See the GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License along with
+ GNU Taler; see the file COPYING.  If not, see <http://www.gnu.org/licenses/>
+ */
+
+/**
+ *
+ * @author Sebastian Javier Marchano (sebasjm)
+ */
+
+import { HttpStatusCode } from "@gnu-taler/taler-util";
+import {
+  ErrorType,
+  HttpError,
+  useTranslationContext,
+} from "@gnu-taler/web-util/browser";
+import { Fragment, VNode, h } from "preact";
+import { useState } from "preact/hooks";
+import { Loading } from "../../../../components/exception/loading.js";
+import { NotificationCard } from "../../../../components/menu/index.js";
+import { MerchantBackend } from "../../../../declaration.js";
+import { useInstanceOtpDevices, useOtpDeviceAPI } from 
"../../../../hooks/otp.js";
+import { Notification } from "../../../../utils/types.js";
+import { ListPage } from "./ListPage.js";
+import { useBankAccountAPI, useInstanceBankAccounts } from 
"../../../../hooks/bank.js";
+
+interface Props {
+  onUnauthorized: () => VNode;
+  onLoadError: (error: HttpError<MerchantBackend.ErrorDetail>) => VNode;
+  onNotFound: () => VNode;
+  onCreate: () => void;
+  onSelect: (id: string) => void;
+}
+
+export default function ListOtpDevices({
+  onUnauthorized,
+  onLoadError,
+  onCreate,
+  onSelect,
+  onNotFound,
+}: Props): VNode {
+  const [position, setPosition] = useState<string | undefined>(undefined);
+  const { i18n } = useTranslationContext();
+  const [notif, setNotif] = useState<Notification | undefined>(undefined);
+  const { deleteBankAccount } = useBankAccountAPI();
+  const result = useInstanceBankAccounts({ position }, (id) => 
setPosition(id));
+
+  if (result.loading) return <Loading />;
+  if (!result.ok) {
+    if (
+      result.type === ErrorType.CLIENT &&
+      result.status === HttpStatusCode.Unauthorized
+    )
+      return onUnauthorized();
+    if (
+      result.type === ErrorType.CLIENT &&
+      result.status === HttpStatusCode.NotFound
+    )
+      return onNotFound();
+    return onLoadError(result);
+  }
+
+  return (
+    <Fragment>
+      <NotificationCard notification={notif} />
+
+      <ListPage
+        devices={result.data.accounts}
+        onLoadMoreBefore={
+          result.isReachingStart ? result.loadMorePrev : undefined
+        }
+        onLoadMoreAfter={result.isReachingEnd ? result.loadMore : undefined}
+        onCreate={onCreate}
+        onSelect={(e) => {
+          onSelect(e.h_wire);
+        }}
+        onDelete={(e: MerchantBackend.BankAccounts.BankAccountEntry) =>
+          deleteBankAccount(e.h_wire)
+            .then(() =>
+              setNotif({
+                message: i18n.str`bank account delete successfully`,
+                type: "SUCCESS",
+              }),
+            )
+            .catch((error) =>
+              setNotif({
+                message: i18n.str`could not delete the bank account`,
+                type: "ERROR",
+                description: error.message,
+              }),
+            )
+        }
+      />
+    </Fragment>
+  );
+}
diff --git 
a/packages/auditor-backoffice-ui/src/paths/instance/accounts/update/Update.stories.tsx
 
b/packages/auditor-backoffice-ui/src/paths/instance/accounts/update/Update.stories.tsx
new file mode 100644
index 000000000..d6b1d65e0
--- /dev/null
+++ 
b/packages/auditor-backoffice-ui/src/paths/instance/accounts/update/Update.stories.tsx
@@ -0,0 +1,32 @@
+/*
+ This file is part of GNU Taler
+ (C) 2021-2023 Taler Systems S.A.
+
+ GNU Taler is free software; you can redistribute it and/or modify it under the
+ terms of the GNU General Public License as published by the Free Software
+ Foundation; either version 3, or (at your option) any later version.
+
+ GNU Taler is distributed in the hope that it will be useful, but WITHOUT ANY
+ WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
+ A PARTICULAR PURPOSE.  See the GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License along with
+ GNU Taler; see the file COPYING.  If not, see <http://www.gnu.org/licenses/>
+ */
+
+/**
+ *
+ * @author Sebastian Javier Marchano (sebasjm)
+ */
+
+import { h, VNode, FunctionalComponent } from "preact";
+import { UpdatePage as TestedComponent } from "./UpdatePage.js";
+
+export default {
+  title: "Pages/OtpDevices/Update",
+  component: TestedComponent,
+  argTypes: {
+    onUpdate: { action: "onUpdate" },
+    onBack: { action: "onBack" },
+  },
+};
diff --git 
a/packages/auditor-backoffice-ui/src/paths/instance/accounts/update/UpdatePage.tsx
 
b/packages/auditor-backoffice-ui/src/paths/instance/accounts/update/UpdatePage.tsx
new file mode 100644
index 000000000..e0e0ba7ed
--- /dev/null
+++ 
b/packages/auditor-backoffice-ui/src/paths/instance/accounts/update/UpdatePage.tsx
@@ -0,0 +1,195 @@
+/*
+ This file is part of GNU Taler
+ (C) 2021-2023 Taler Systems S.A.
+
+ GNU Taler is free software; you can redistribute it and/or modify it under the
+ terms of the GNU General Public License as published by the Free Software
+ Foundation; either version 3, or (at your option) any later version.
+
+ GNU Taler is distributed in the hope that it will be useful, but WITHOUT ANY
+ WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
+ A PARTICULAR PURPOSE.  See the GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License along with
+ GNU Taler; see the file COPYING.  If not, see <http://www.gnu.org/licenses/>
+ */
+
+/**
+ *
+ * @author Sebastian Javier Marchano (sebasjm)
+ */
+
+import { useTranslationContext } from "@gnu-taler/web-util/browser";
+import { Fragment, h, VNode } from "preact";
+import { useState } from "preact/hooks";
+import { AsyncButton } from "../../../../components/exception/AsyncButton.js";
+import {
+  FormErrors,
+  FormProvider,
+} from "../../../../components/form/FormProvider.js";
+import { Input } from "../../../../components/form/Input.js";
+import { MerchantBackend, WithId } from "../../../../declaration.js";
+import { InputSelector } from "../../../../components/form/InputSelector.js";
+import { InputPaytoForm } from "../../../../components/form/InputPaytoForm.js";
+import { undefinedIfEmpty } from "../../../../utils/table.js";
+
+type Entity = MerchantBackend.BankAccounts.BankAccountEntry
+  & WithId;
+
+const accountAuthType = ["unedit", "none", "basic"];
+interface Props {
+  onUpdate: (d: MerchantBackend.BankAccounts.AccountPatchDetails) => 
Promise<void>;
+  onBack?: () => void;
+  account: Entity;
+}
+
+
+export function UpdatePage({ account, onUpdate, onBack }: Props): VNode {
+  const { i18n } = useTranslationContext();
+
+  const [state, setState] = 
useState<Partial<MerchantBackend.BankAccounts.AccountPatchDetails>>(account);
+
+  const errors: FormErrors<MerchantBackend.BankAccounts.AccountPatchDetails> = 
{
+    credit_facade_url: !state.credit_facade_url ? i18n.str`required` : 
!isValidURL(state.credit_facade_url) ? i18n.str`invalid url` : undefined,
+    credit_facade_credentials: undefinedIfEmpty({
+
+      username: state.credit_facade_credentials?.type !== "basic" ? undefined
+        : !state.credit_facade_credentials.username ? i18n.str`required` : 
undefined,
+
+      password: state.credit_facade_credentials?.type !== "basic" ? undefined
+        : !state.credit_facade_credentials.password ? i18n.str`required` : 
undefined,
+
+      repeatPassword: state.credit_facade_credentials?.type !== "basic" ? 
undefined
+        : !(state.credit_facade_credentials as any).repeatPassword ? 
i18n.str`required` :
+          (state.credit_facade_credentials as any).repeatPassword !== 
state.credit_facade_credentials.password ? i18n.str`doesnt match`
+            : undefined,
+    }),
+  };
+
+  const hasErrors = Object.keys(errors).some(
+    (k) => (errors as any)[k] !== undefined,
+  );
+
+  const submitForm = () => {
+    if (hasErrors) return Promise.reject();
+
+    const creds: typeof state.credit_facade_credentials =
+      state.credit_facade_credentials?.type === "basic" ? {
+        type: "basic",
+        password: state.credit_facade_credentials.password,
+        username: state.credit_facade_credentials.username,
+      } : state.credit_facade_credentials?.type === "none" ? {
+        type: "none"
+      } : undefined;
+
+    return onUpdate({
+      credit_facade_credentials: creds,
+      credit_facade_url: state.credit_facade_url,
+    });
+  };
+
+  return (
+    <div>
+      <section class="section">
+        <section class="hero is-hero-bar">
+          <div class="hero-body">
+            <div class="level">
+              <div class="level-left">
+                <div class="level-item">
+                  <span class="is-size-4">
+                    Account: <b>{account.id.substring(0, 8)}...</b>
+                  </span>
+                </div>
+              </div>
+            </div>
+          </div>
+        </section>
+        <hr />
+
+        <section class="section is-main-section">
+          <div class="columns">
+            <div class="column is-four-fifths">
+              <FormProvider
+                object={state}
+                valueHandler={setState}
+                errors={errors}
+              >
+                <InputPaytoForm<Entity>
+                  name="payto_uri"
+                  label={i18n.str`Account`}
+                  readonly
+                />
+                <Input<Entity>
+                  name="credit_facade_url"
+                  label={i18n.str`Account info URL`}
+                  help="https://bank.com";
+                  expand
+                  tooltip={i18n.str`From where the merchant can download 
information about incoming wire transfers to this account`}
+                />
+                <InputSelector
+                  name="credit_facade_credentials.type"
+                  label={i18n.str`Auth type`}
+                  tooltip={i18n.str`Choose the authentication type for the 
account info URL`}
+                  values={accountAuthType}
+                  toStr={(str) => {
+                    if (str === "none") return "Without authentication";
+                    if (str === "basic") return "With authentication";
+                    return "Do not change"
+                  }}
+                />
+                {state.credit_facade_credentials?.type === "basic" ? (
+                  <Fragment>
+                    <Input
+                      name="credit_facade_credentials.username"
+                      label={i18n.str`Username`}
+                      tooltip={i18n.str`Username to access the account 
information.`}
+                    />
+                    <Input
+                      name="credit_facade_credentials.password"
+                      inputType="password"
+                      label={i18n.str`Password`}
+                      tooltip={i18n.str`Password to access the account 
information.`}
+                    />
+                    <Input
+                      name="credit_facade_credentials.repeatPassword"
+                      inputType="password"
+                      label={i18n.str`Repeat password`}
+                    />
+                  </Fragment>
+                ) : undefined}
+              </FormProvider>
+
+              <div class="buttons is-right mt-5">
+                {onBack && (
+                  <button class="button" onClick={onBack}>
+                    <i18n.Translate>Cancel</i18n.Translate>
+                  </button>
+                )}
+                <AsyncButton
+                  disabled={hasErrors}
+                  data-tooltip={
+                    hasErrors
+                      ? i18n.str`Need to complete marked fields`
+                      : "confirm operation"
+                  }
+                  onClick={submitForm}
+                >
+                  <i18n.Translate>Confirm</i18n.Translate>
+                </AsyncButton>
+              </div>
+            </div>
+          </div>
+        </section>
+      </section>
+    </div>
+  );
+}
+
+function isValidURL(s: string): boolean {
+  try {
+    const u = new URL(s)
+    return true;
+  } catch (e) {
+    return false;
+  }
+}
diff --git 
a/packages/auditor-backoffice-ui/src/paths/instance/accounts/update/index.tsx 
b/packages/auditor-backoffice-ui/src/paths/instance/accounts/update/index.tsx
new file mode 100644
index 000000000..44dee7651
--- /dev/null
+++ 
b/packages/auditor-backoffice-ui/src/paths/instance/accounts/update/index.tsx
@@ -0,0 +1,96 @@
+/*
+ This file is part of GNU Taler
+ (C) 2021-2023 Taler Systems S.A.
+
+ GNU Taler is free software; you can redistribute it and/or modify it under the
+ terms of the GNU General Public License as published by the Free Software
+ Foundation; either version 3, or (at your option) any later version.
+
+ GNU Taler is distributed in the hope that it will be useful, but WITHOUT ANY
+ WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
+ A PARTICULAR PURPOSE.  See the GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License along with
+ GNU Taler; see the file COPYING.  If not, see <http://www.gnu.org/licenses/>
+ */
+
+/**
+ *
+ * @author Sebastian Javier Marchano (sebasjm)
+ */
+
+import { HttpStatusCode } from "@gnu-taler/taler-util";
+import {
+  ErrorType,
+  HttpError,
+  useTranslationContext,
+} from "@gnu-taler/web-util/browser";
+import { Fragment, VNode, h } from "preact";
+import { useState } from "preact/hooks";
+import { Loading } from "../../../../components/exception/loading.js";
+import { NotificationCard } from "../../../../components/menu/index.js";
+import { MerchantBackend, WithId } from "../../../../declaration.js";
+import { useBankAccountAPI, useBankAccountDetails } from 
"../../../../hooks/bank.js";
+import { Notification } from "../../../../utils/types.js";
+import { UpdatePage } from "./UpdatePage.js";
+
+export type Entity = MerchantBackend.BankAccounts.AccountPatchDetails & WithId;
+
+interface Props {
+  onBack?: () => void;
+  onConfirm: () => void;
+  onUnauthorized: () => VNode;
+  onNotFound: () => VNode;
+  onLoadError: (e: HttpError<MerchantBackend.ErrorDetail>) => VNode;
+  bid: string;
+}
+export default function UpdateValidator({
+  bid,
+  onConfirm,
+  onBack,
+  onUnauthorized,
+  onNotFound,
+  onLoadError,
+}: Props): VNode {
+  const { updateBankAccount } = useBankAccountAPI();
+  const result = useBankAccountDetails(bid);
+  const [notif, setNotif] = useState<Notification | undefined>(undefined);
+
+  const { i18n } = useTranslationContext();
+
+  if (result.loading) return <Loading />;
+  if (!result.ok) {
+    if (
+      result.type === ErrorType.CLIENT &&
+      result.status === HttpStatusCode.Unauthorized
+    )
+      return onUnauthorized();
+    if (
+      result.type === ErrorType.CLIENT &&
+      result.status === HttpStatusCode.NotFound
+    )
+      return onNotFound();
+    return onLoadError(result);
+  }
+
+  return (
+    <Fragment>
+      <NotificationCard notification={notif} />
+      <UpdatePage
+        account={{ ...result.data, id: bid }}
+        onBack={onBack}
+        onUpdate={(data) => {
+          return updateBankAccount(bid, data)
+            .then(onConfirm)
+            .catch((error) => {
+              setNotif({
+                message: i18n.str`could not update account`,
+                type: "ERROR",
+                description: error.message,
+              });
+            });
+        }}
+      />
+    </Fragment>
+  );
+}
diff --git 
a/packages/auditor-backoffice-ui/src/paths/instance/deposit_confirmations/create/Create.stories.tsx
 
b/packages/auditor-backoffice-ui/src/paths/instance/deposit_confirmations/create/Create.stories.tsx
new file mode 100644
index 000000000..2fc0819bb
--- /dev/null
+++ 
b/packages/auditor-backoffice-ui/src/paths/instance/deposit_confirmations/create/Create.stories.tsx
@@ -0,0 +1,43 @@
+/*
+ This file is part of GNU Taler
+ (C) 2021-2023 Taler Systems S.A.
+
+ GNU Taler is free software; you can redistribute it and/or modify it under the
+ terms of the GNU General Public License as published by the Free Software
+ Foundation; either version 3, or (at your option) any later version.
+
+ GNU Taler is distributed in the hope that it will be useful, but WITHOUT ANY
+ WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
+ A PARTICULAR PURPOSE.  See the GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License along with
+ GNU Taler; see the file COPYING.  If not, see <http://www.gnu.org/licenses/>
+ */
+
+/**
+ *
+ * @author Sebastian Javier Marchano (sebasjm)
+ */
+
+import { h, VNode, FunctionalComponent } from "preact";
+import { CreatePage as TestedComponent } from "./CreatePage.js";
+
+export default {
+  title: "Pages/Product/Create",
+  component: TestedComponent,
+  argTypes: {
+    onCreate: { action: "onCreate" },
+    onBack: { action: "onBack" },
+  },
+};
+
+function createExample<Props>(
+  Component: FunctionalComponent<Props>,
+  props: Partial<Props>,
+) {
+  const r = (args: any) => <Component {...args} />;
+  r.args = props;
+  return r;
+}
+
+export const Example = createExample(TestedComponent, {});
diff --git 
a/packages/auditor-backoffice-ui/src/paths/instance/deposit_confirmations/create/CreatePage.tsx
 
b/packages/auditor-backoffice-ui/src/paths/instance/deposit_confirmations/create/CreatePage.tsx
new file mode 100644
index 000000000..becaf8f3a
--- /dev/null
+++ 
b/packages/auditor-backoffice-ui/src/paths/instance/deposit_confirmations/create/CreatePage.tsx
@@ -0,0 +1,80 @@
+/*
+ This file is part of GNU Taler
+ (C) 2021-2023 Taler Systems S.A.
+
+ GNU Taler is free software; you can redistribute it and/or modify it under the
+ terms of the GNU General Public License as published by the Free Software
+ Foundation; either version 3, or (at your option) any later version.
+
+ GNU Taler is distributed in the hope that it will be useful, but WITHOUT ANY
+ WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
+ A PARTICULAR PURPOSE.  See the GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License along with
+ GNU Taler; see the file COPYING.  If not, see <http://www.gnu.org/licenses/>
+ */
+
+/**
+ *
+ * @author Sebastian Javier Marchano (sebasjm)
+ */
+
+import { useTranslationContext } from "@gnu-taler/web-util/browser";
+import { h, VNode } from "preact";
+import { AsyncButton } from "../../../../components/exception/AsyncButton.js";
+import { ProductForm } from "../../../../components/product/ProductForm.js";
+import { MerchantBackend } from "../../../../declaration.js";
+import { useListener } from "../../../../hooks/listener.js";
+
+type Entity = MerchantBackend.Products.ProductAddDetail & {
+  product_id: string;
+};
+
+interface Props {
+  onCreate: (d: Entity) => Promise<void>;
+  onBack?: () => void;
+}
+
+export function CreatePage({ onCreate, onBack }: Props): VNode {
+  const [submitForm, addFormSubmitter] = useListener<Entity | undefined>(
+    (result) => {
+      if (result) return onCreate(result);
+      return Promise.reject();
+    },
+  );
+
+  const { i18n } = useTranslationContext();
+
+  return (
+    <div>
+      <section class="section is-main-section">
+        <div class="columns">
+          <div class="column" />
+          <div class="column is-four-fifths">
+            <ProductForm onSubscribe={addFormSubmitter} />
+
+            <div class="buttons is-right mt-5">
+              {onBack && (
+                <button class="button" onClick={onBack}>
+                  <i18n.Translate>Cancel</i18n.Translate>
+                </button>
+              )}
+              <AsyncButton
+                onClick={submitForm}
+                data-tooltip={
+                  !submitForm
+                    ? i18n.str`Need to complete marked fields`
+                    : "confirm operation"
+                }
+                disabled={!submitForm}
+              >
+                <i18n.Translate>Confirm</i18n.Translate>
+              </AsyncButton>
+            </div>
+          </div>
+          <div class="column" />
+        </div>
+      </section>
+    </div>
+  );
+}
diff --git 
a/packages/auditor-backoffice-ui/src/paths/instance/deposit_confirmations/create/CreatedSuccessfully.tsx
 
b/packages/auditor-backoffice-ui/src/paths/instance/deposit_confirmations/create/CreatedSuccessfully.tsx
new file mode 100644
index 000000000..6b02430cc
--- /dev/null
+++ 
b/packages/auditor-backoffice-ui/src/paths/instance/deposit_confirmations/create/CreatedSuccessfully.tsx
@@ -0,0 +1,72 @@
+/*
+ This file is part of GNU Taler
+ (C) 2021-2023 Taler Systems S.A.
+
+ GNU Taler is free software; you can redistribute it and/or modify it under the
+ terms of the GNU General Public License as published by the Free Software
+ Foundation; either version 3, or (at your option) any later version.
+
+ GNU Taler is distributed in the hope that it will be useful, but WITHOUT ANY
+ WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
+ A PARTICULAR PURPOSE.  See the GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License along with
+ GNU Taler; see the file COPYING.  If not, see <http://www.gnu.org/licenses/>
+ */
+import { h, VNode } from "preact";
+import { CreatedSuccessfully as Template } from 
"../../../../components/notifications/CreatedSuccessfully.js";
+import { Entity } from "./index.js";
+import emptyImage from "../../assets/empty.png";
+
+interface Props {
+  entity: Entity;
+  onConfirm: () => void;
+  onCreateAnother?: () => void;
+}
+
+export function CreatedSuccessfully({
+  entity,
+  onConfirm,
+  onCreateAnother,
+}: Props): VNode {
+  return (
+    <Template onConfirm={onConfirm} onCreateAnother={onCreateAnother}>
+      <div class="field is-horizontal">
+        <div class="field-label is-normal">
+          <label class="label">Image</label>
+        </div>
+        <div class="field-body is-flex-grow-3">
+          <div class="field">
+            <p class="control">
+              <img src={entity.image} style={{ width: 200, height: 200 }} />
+            </p>
+          </div>
+        </div>
+      </div>
+      <div class="field is-horizontal">
+        <div class="field-label is-normal">
+          <label class="label">Description</label>
+        </div>
+        <div class="field-body is-flex-grow-3">
+          <div class="field">
+            <p class="control">
+              <textarea class="input" readonly value={entity.description} />
+            </p>
+          </div>
+        </div>
+      </div>
+      <div class="field is-horizontal">
+        <div class="field-label is-normal">
+          <label class="label">Price</label>
+        </div>
+        <div class="field-body is-flex-grow-3">
+          <div class="field">
+            <p class="control">
+              <input class="input" readonly value={entity.price} />
+            </p>
+          </div>
+        </div>
+      </div>
+    </Template>
+  );
+}
diff --git 
a/packages/auditor-backoffice-ui/src/paths/instance/deposit_confirmations/create/index.tsx
 
b/packages/auditor-backoffice-ui/src/paths/instance/deposit_confirmations/create/index.tsx
new file mode 100644
index 000000000..4b59e9807
--- /dev/null
+++ 
b/packages/auditor-backoffice-ui/src/paths/instance/deposit_confirmations/create/index.tsx
@@ -0,0 +1,60 @@
+/*
+ This file is part of GNU Taler
+ (C) 2021-2023 Taler Systems S.A.
+
+ GNU Taler is free software; you can redistribute it and/or modify it under the
+ terms of the GNU General Public License as published by the Free Software
+ Foundation; either version 3, or (at your option) any later version.
+
+ GNU Taler is distributed in the hope that it will be useful, but WITHOUT ANY
+ WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
+ A PARTICULAR PURPOSE.  See the GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License along with
+ GNU Taler; see the file COPYING.  If not, see <http://www.gnu.org/licenses/>
+ */
+
+/**
+ *
+ * @author Sebastian Javier Marchano (sebasjm)
+ */
+
+import { useTranslationContext } from "@gnu-taler/web-util/browser";
+import { Fragment, h, VNode } from "preact";
+import { useState } from "preact/hooks";
+import { NotificationCard } from "../../../../components/menu/index.js";
+import { AuditorBackend } from "../../../../declaration.js";
+import { useDepositConfirmationAPI } from 
"../../../../hooks/deposit_confirmations.js";
+import { Notification } from "../../../../utils/types.js";
+import { CreatePage } from "./CreatePage.js";
+
+export type Entity = 
AuditorBackend.DepositConfirmation.DepositConfirmationDetail;
+interface Props {
+  onBack?: () => void;
+  onConfirm: () => void;
+}
+export default function CreateProduct({ onConfirm, onBack }: Props): VNode {
+  const { createProduct } = useProductAPI();
+  const [notif, setNotif] = useState<Notification | undefined>(undefined);
+  const { i18n } = useTranslationContext();
+
+  return (
+    <Fragment>
+      <NotificationCard notification={notif} />
+      <CreatePage
+        onBack={onBack}
+        onCreate={(request: MerchantBackend.Products.ProductAddDetail) => {
+          return createProduct(request)
+            .then(() => onConfirm())
+            .catch((error) => {
+              setNotif({
+                message: i18n.str`could not create product`,
+                type: "ERROR",
+                description: error.message,
+              });
+            });
+        }}
+      />
+    </Fragment>
+  );
+}
diff --git 
a/packages/auditor-backoffice-ui/src/paths/instance/deposit_confirmations/list/List.stories.tsx
 
b/packages/auditor-backoffice-ui/src/paths/instance/deposit_confirmations/list/List.stories.tsx
new file mode 100644
index 000000000..c2c4d548c
--- /dev/null
+++ 
b/packages/auditor-backoffice-ui/src/paths/instance/deposit_confirmations/list/List.stories.tsx
@@ -0,0 +1,61 @@
+/*
+ This file is part of GNU Taler
+ (C) 2021-2023 Taler Systems S.A.
+
+ GNU Taler is free software; you can redistribute it and/or modify it under the
+ terms of the GNU General Public License as published by the Free Software
+ Foundation; either version 3, or (at your option) any later version.
+
+ GNU Taler is distributed in the hope that it will be useful, but WITHOUT ANY
+ WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
+ A PARTICULAR PURPOSE.  See the GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License along with
+ GNU Taler; see the file COPYING.  If not, see <http://www.gnu.org/licenses/>
+ */
+
+/**
+ *
+ * @author Sebastian Javier Marchano (sebasjm)
+ */
+
+import { h, VNode, FunctionalComponent } from "preact";
+import { CardTable as TestedComponent } from "./Table.js";
+
+export default {
+  title: "Pages/Product/List",
+  component: TestedComponent,
+  argTypes: {
+    onCreate: { action: "onCreate" },
+    onSelect: { action: "onSelect" },
+    onDelete: { action: "onDelete" },
+    onUpdate: { action: "onUpdate" },
+  },
+};
+
+function createExample<Props>(
+  Component: FunctionalComponent<Props>,
+  props: Partial<Props>,
+) {
+  const r = (args: any) => <Component {...args} />;
+  r.args = props;
+  return r;
+}
+
+export const Example = createExample(TestedComponent, {
+  instances: [
+    {
+      id: "orderid",
+      description: "description1",
+      description_i18n: {} as any,
+      image: "",
+      price: "TESTKUDOS:10",
+      taxes: [],
+      total_lost: 10,
+      total_sold: 5,
+      total_stock: 15,
+      unit: "bar",
+      address: {},
+    },
+  ],
+});
diff --git 
a/packages/auditor-backoffice-ui/src/paths/instance/deposit_confirmations/list/Table.tsx
 
b/packages/auditor-backoffice-ui/src/paths/instance/deposit_confirmations/list/Table.tsx
new file mode 100644
index 000000000..ffd1f12e5
--- /dev/null
+++ 
b/packages/auditor-backoffice-ui/src/paths/instance/deposit_confirmations/list/Table.tsx
@@ -0,0 +1,496 @@
+/*
+ This file is part of GNU Taler
+ (C) 2021-2023 Taler Systems S.A.
+
+ GNU Taler is free software; you can redistribute it and/or modify it under the
+ terms of the GNU General Public License as published by the Free Software
+ Foundation; either version 3, or (at your option) any later version.
+
+ GNU Taler is distributed in the hope that it will be useful, but WITHOUT ANY
+ WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
+ A PARTICULAR PURPOSE.  See the GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License along with
+ GNU Taler; see the file COPYING.  If not, see <http://www.gnu.org/licenses/>
+ */
+
+/**
+ *
+ * @author Sebastian Javier Marchano (sebasjm)
+ */
+
+import { Amounts } from "@gnu-taler/taler-util";
+import { useTranslationContext } from "@gnu-taler/web-util/browser";
+import { format } from "date-fns";
+import { ComponentChildren, Fragment, h, VNode } from "preact";
+import { StateUpdater, useState } from "preact/hooks";
+import emptyImage from "../../../../assets/empty.png";
+import {
+  FormErrors,
+  FormProvider,
+} from "../../../../components/form/FormProvider.js";
+import { InputCurrency } from "../../../../components/form/InputCurrency.js";
+import { InputNumber } from "../../../../components/form/InputNumber.js";
+import { AuditorBackend, WithId } from "../../../../declaration.js";
+import { dateFormatForSettings, useSettings } from 
"../../../../hooks/useSettings.js";
+
+type Entity = AuditorBackend.DepositConfirmation.DepositConfirmationDetail & 
WithId;
+
+interface Props {
+  instances: Entity[];
+  onDelete: (id: Entity) => void;
+  onSelect: (depositConfirmation: Entity) => void;
+  onUpdate: (
+    id: string,
+    data: AuditorBackend.DepositConfirmation.DepositConfirmationDetail,
+  ) => Promise<void>;
+  onCreate: () => void;
+  selected?: boolean;
+}
+
+export function CardTable({
+  instances,
+  onCreate,
+  onSelect,
+  onUpdate,
+  onDelete,
+}: Props): VNode {
+  const [rowSelection, rowSelectionHandler] = useState<string | undefined>(
+    undefined,
+  );
+  const { i18n } = useTranslationContext();
+  return (
+    <div class="card has-table">
+      <header class="card-header">
+        <p class="card-header-title">
+          <span class="icon">
+            <i class="mdi mdi-shopping" />
+          </span>
+          <i18n.Translate>Deposit Confirmations</i18n.Translate>
+        </p>
+        <div class="card-header-icon" aria-label="more options">
+          <span
+            class="has-tooltip-left"
+            data-tooltip={i18n.str`add deposit-confirmation`}
+          >
+            <button class="button is-info" type="button" onClick={onCreate}>
+              <span class="icon is-small">
+                <i class="mdi mdi-plus mdi-36px" />
+              </span>
+            </button>
+          </span>
+        </div>
+      </header>
+      <div class="card-content">
+        <div class="b-table has-pagination">
+          <div class="table-wrapper has-mobile-cards">
+            {instances.length > 0 ? (
+              <Table
+                instances={instances}
+                onSelect={onSelect}
+                onDelete={onDelete}
+                onUpdate={onUpdate}
+                rowSelection={rowSelection}
+                rowSelectionHandler={rowSelectionHandler}
+              />
+            ) : (
+              <EmptyTable />
+            )}
+          </div>
+        </div>
+      </div>
+    </div>
+  );
+}
+interface TableProps {
+  rowSelection: string | undefined;
+  instances: Entity[];
+  onSelect: (id: Entity) => void;
+  onUpdate: (
+    id: string,
+    data: AuditorBackend.DepositConfirmation.DepositConfirmationDetail,
+  ) => Promise<void>;
+  onDelete: (serial_id: Entity) => void;
+  rowSelectionHandler: StateUpdater<string | undefined>;
+}
+
+function Table({
+  rowSelection,
+  rowSelectionHandler,
+  instances,
+  onSelect,
+  onUpdate,
+  onDelete,
+}: TableProps): VNode {
+  const { i18n } = useTranslationContext();
+  const [settings] = useSettings();
+  return (
+    <div class="table-container">
+      <table class="table is-fullwidth is-striped is-hoverable is-fullwidth">
+        <thead>
+          <tr>
+            <th>
+              <i18n.Translate>Image</i18n.Translate>
+            </th>
+            <th>
+              <i18n.Translate>Description</i18n.Translate>
+            </th>
+            <th>
+              <i18n.Translate>Price per unit</i18n.Translate>
+            </th>
+            <th>
+              <i18n.Translate>Taxes</i18n.Translate>
+            </th>
+            <th>
+              <i18n.Translate>Sales</i18n.Translate>
+            </th>
+            <th>
+              <i18n.Translate>Stock</i18n.Translate>
+            </th>
+            <th>
+              <i18n.Translate>Sold</i18n.Translate>
+            </th>
+            <th />
+          </tr>
+        </thead>
+        <tbody>
+          {instances.map((i) => {
+            const restStockInfo = !i.next_restock
+              ? ""
+              : i.next_restock.t_s === "never"
+                ? "never"
+                : `restock at ${format(
+                  new Date(i.next_restock.t_s * 1000),
+                  dateFormatForSettings(settings),
+                )}`;
+            let stockInfo: ComponentChildren = "";
+            if (i.total_stock < 0) {
+              stockInfo = "infinite";
+            } else {
+              const totalStock = i.total_stock - i.total_lost - i.total_sold;
+              stockInfo = (
+                <label title={restStockInfo}>
+                  {totalStock} {i.unit}
+                </label>
+              );
+            }
+
+            const isFree = Amounts.isZero(Amounts.parseOrThrow(i.price));
+
+            return (
+              <Fragment key={i.id}>
+                <tr key="info">
+                  <td
+                    onClick={() =>
+                      rowSelection !== i.id && rowSelectionHandler(i.id)
+                    }
+                    style={{ cursor: "pointer" }}
+                  >
+                    <img
+                      src={i.image ? i.image : emptyImage}
+                      style={{
+                        border: "solid black 1px",
+                        maxHeight: "2em",
+                        width: "auto",
+                        height: "auto",
+                      }}
+                    />
+                  </td>
+                  <td
+                    class="has-tooltip-right"                    
+                    data-tooltip={i.description}
+                    onClick={() =>
+                      rowSelection !== i.id && rowSelectionHandler(i.id)
+                    }
+                    style={{ cursor: "pointer" }}
+                  >
+                    {i.description.length > 30  ? i.description.substring(0, 
30) + "..." : i.description}
+                  </td>
+                  <td
+                    onClick={() =>
+                      rowSelection !== i.id && rowSelectionHandler(i.id)
+                    }
+                    style={{ cursor: "pointer" }}
+                  >
+                    {isFree ? i18n.str`free` : `${i.price} / ${i.unit}`}
+                  </td>
+                  <td
+                    onClick={() =>
+                      rowSelection !== i.id && rowSelectionHandler(i.id)
+                    }
+                    style={{ cursor: "pointer" }}
+                  >
+                    {sum(i.taxes)}
+                  </td>
+                  <td
+                    onClick={() =>
+                      rowSelection !== i.id && rowSelectionHandler(i.id)
+                    }
+                    style={{ cursor: "pointer" }}
+                  >
+                    {difference(i.price, sum(i.taxes))}
+                  </td>
+                  <td
+                    onClick={() =>
+                      rowSelection !== i.id && rowSelectionHandler(i.id)
+                    }
+                    style={{ cursor: "pointer" }}
+                  >
+                    {stockInfo}
+                  </td>
+                  <td
+                    onClick={() =>
+                      rowSelection !== i.id && rowSelectionHandler(i.id)
+                    }
+                    style={{ cursor: "pointer" }}
+                  >
+                    <span style={{"whiteSpace":"nowrap"}}>
+
+                    {i.total_sold} {i.unit}
+                    </span>
+                  </td>
+                  <td class="is-actions-cell right-sticky">
+                    <div class="buttons is-right">
+                      <span
+                        class="has-tooltip-bottom"
+                        data-tooltip={i18n.str`go to product update page`}
+                      >
+                        <button
+                          class="button is-small is-success "
+                          type="button"
+                          onClick={(): void => onSelect(i)}
+                        >
+                          <i18n.Translate>Update</i18n.Translate>
+                        </button>
+                      </span>
+                      <span
+                        class="has-tooltip-left"
+                        data-tooltip={i18n.str`remove this product from the 
database`}
+                      >
+                        <button
+                          class="button is-small is-danger"
+                          type="button"
+                          onClick={(): void => onDelete(i)}
+                        >
+                          <i18n.Translate>Delete</i18n.Translate>
+                        </button>
+                      </span>
+                    </div>
+                  </td>
+                </tr>
+                {rowSelection === i.id && (
+                  <tr key="form">
+                    <td colSpan={10}>
+                      <FastProductUpdateForm
+                        product={i}
+                        onUpdate={(prod) =>
+                          onUpdate(i.id, prod).then((r) =>
+                            rowSelectionHandler(undefined),
+                          )
+                        }
+                        onCancel={() => rowSelectionHandler(undefined)}
+                      />
+                    </td>
+                  </tr>
+                )}
+              </Fragment>
+            );
+          })}
+        </tbody>
+      </table>
+    </div>
+  );
+}
+
+interface FastProductUpdateFormProps {
+  product: Entity;
+  onUpdate: (
+    data: MerchantBackend.Products.ProductPatchDetail,
+  ) => Promise<void>;
+  onCancel: () => void;
+}
+interface FastProductUpdate {
+  incoming: number;
+  lost: number;
+  price: string;
+}
+interface UpdatePrice {
+  price: string;
+}
+
+function FastProductWithInfiniteStockUpdateForm({
+  product,
+  onUpdate,
+  onCancel,
+}: FastProductUpdateFormProps) {
+  const [value, valueHandler] = useState<UpdatePrice>({ price: product.price 
});
+  const { i18n } = useTranslationContext();
+
+  return (
+    <Fragment>
+      <FormProvider<FastProductUpdate>
+        name="added"
+        object={value}
+        valueHandler={valueHandler as any}
+      >
+        <InputCurrency<FastProductUpdate>
+          name="price"
+          label={i18n.str`Price`}
+          tooltip={i18n.str`update the product with new price`}
+        />
+      </FormProvider>
+
+      <div class="buttons is-expanded">
+
+        <div class="buttons mt-5">
+
+          <button class="button mt-5" onClick={onCancel}>
+            <i18n.Translate>Clone</i18n.Translate>
+          </button>
+        </div>
+        <div class="buttons is-right mt-5">
+          <button class="button" onClick={onCancel}>
+            <i18n.Translate>Cancel</i18n.Translate>
+          </button>
+          <span
+            class="has-tooltip-left"
+            data-tooltip={i18n.str`update product with new price`}
+          >
+            <button
+              class="button is-info"
+              onClick={() =>
+                onUpdate({
+                  ...product,
+                  price: value.price,
+                })
+              }
+            >
+              <i18n.Translate>Confirm update</i18n.Translate>
+            </button>
+          </span>
+        </div>
+      </div>
+    </Fragment>
+  );
+}
+
+function FastProductWithManagedStockUpdateForm({
+  product,
+  onUpdate,
+  onCancel,
+}: FastProductUpdateFormProps) {
+  const [value, valueHandler] = useState<FastProductUpdate>({
+    incoming: 0,
+    lost: 0,
+    price: product.price,
+  });
+
+  const currentStock =
+    product.total_stock - product.total_sold - product.total_lost;
+
+  const errors: FormErrors<FastProductUpdate> = {
+    lost:
+      currentStock + value.incoming < value.lost
+        ? `lost cannot be greater that current + incoming (max ${currentStock 
+ value.incoming
+        })`
+        : undefined,
+  };
+
+  const hasErrors = Object.keys(errors).some(
+    (k) => (errors as any)[k] !== undefined,
+  );
+  const { i18n } = useTranslationContext();
+
+  return (
+    <Fragment>
+      <FormProvider<FastProductUpdate>
+        name="added"
+        errors={errors}
+        object={value}
+        valueHandler={valueHandler as any}
+      >
+        <InputNumber<FastProductUpdate>
+          name="incoming"
+          label={i18n.str`Incoming`}
+          tooltip={i18n.str`add more elements to the inventory`}
+        />
+        <InputNumber<FastProductUpdate>
+          name="lost"
+          label={i18n.str`Lost`}
+          tooltip={i18n.str`report elements lost in the inventory`}
+        />
+        <InputCurrency<FastProductUpdate>
+          name="price"
+          label={i18n.str`Price`}
+          tooltip={i18n.str`new price for the product`}
+        />
+      </FormProvider>
+
+      <div class="buttons is-right mt-5">
+        <button class="button" onClick={onCancel}>
+          <i18n.Translate>Cancel</i18n.Translate>
+        </button>
+        <span
+          class="has-tooltip-left"
+          data-tooltip={
+            hasErrors
+              ? i18n.str`the are value with errors`
+              : i18n.str`update product with new stock and price`
+          }
+        >
+          <button
+            class="button is-info"
+            disabled={hasErrors}
+            onClick={() =>
+              onUpdate({
+                ...product,
+                total_stock: product.total_stock + value.incoming,
+                total_lost: product.total_lost + value.lost,
+                price: value.price,
+              })
+            }
+          >
+            <i18n.Translate>Confirm</i18n.Translate>
+          </button>
+        </span>
+      </div>
+    </Fragment>
+  );
+}
+
+function FastProductUpdateForm(props: FastProductUpdateFormProps) {
+  return props.product.total_stock === -1 ? (
+    <FastProductWithInfiniteStockUpdateForm {...props} />
+  ) : (
+    <FastProductWithManagedStockUpdateForm {...props} />
+  );
+}
+
+function EmptyTable(): VNode {
+  const { i18n } = useTranslationContext();
+  return (
+    <div class="content has-text-grey has-text-centered">
+      <p>
+        <span class="icon is-large">
+          <i class="mdi mdi-emoticon-sad mdi-48px" />
+        </span>
+      </p>
+      <p>
+        <i18n.Translate>
+          There is no products yet, add more pressing the + sign
+        </i18n.Translate>
+      </p>
+    </div>
+  );
+}
+
+function difference(price: string, tax: number) {
+  if (!tax) return price;
+  const ps = price.split(":");
+  const p = parseInt(ps[1], 10);
+  ps[1] = `${p - tax}`;
+  return ps.join(":");
+}
+function sum(taxes: MerchantBackend.Tax[]) {
+  return taxes.reduce((p, c) => p + parseInt(c.tax.split(":")[1], 10), 0);
+}
diff --git 
a/packages/auditor-backoffice-ui/src/paths/instance/deposit_confirmations/list/index.tsx
 
b/packages/auditor-backoffice-ui/src/paths/instance/deposit_confirmations/list/index.tsx
new file mode 100644
index 000000000..dccb3ef25
--- /dev/null
+++ 
b/packages/auditor-backoffice-ui/src/paths/instance/deposit_confirmations/list/index.tsx
@@ -0,0 +1,151 @@
+/*
+ This file is part of GNU Taler
+ (C) 2021-2024 Taler Systems S.A.
+
+ GNU Taler is free software; you can redistribute it and/or modify it under the
+ terms of the GNU General Public License as published by the Free Software
+ Foundation; either version 3, or (at your option) any later version.
+
+ GNU Taler is distributed in the hope that it will be useful, but WITHOUT ANY
+ WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
+ A PARTICULAR PURPOSE.  See the GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License along with
+ GNU Taler; see the file COPYING.  If not, see <http://www.gnu.org/licenses/>
+ */
+
+/**
+ *
+ * @author Sebastian Javier Marchano (sebasjm)
+ * @author Nic Eigel
+ */
+
+import {
+  ErrorType,
+  HttpError,
+  useTranslationContext,
+} from "@gnu-taler/web-util/browser";
+import { h, VNode } from "preact";
+import { useState } from "preact/hooks";
+import { Loading } from "../../../../components/exception/loading.js";
+import { NotificationCard } from "../../../../components/menu/index.js";
+import { AuditorBackend, WithId } from "../../../../declaration.js";
+import {
+  useDepositConfirmation,
+  useDepositConfirmationAPI,
+} from "../../../../hooks/deposit_confirmations.js";
+import { Notification } from "../../../../utils/types.js";
+import { CardTable } from "./Table.js";
+import { HttpStatusCode } from "@gnu-taler/taler-util";
+import { ConfirmModal, DeleteModal } from 
"../../../../components/modal/index.js";
+import { JumpToElementById } from 
"../../../../components/form/JumpToElementById.js";
+
+interface Props {
+  onUnauthorized: () => VNode;
+  onNotFound: () => VNode;
+  onCreate: () => void;
+  onSelect: (id: string) => void;
+  onLoadError: (e: HttpError<AuditorBackend.ErrorDetail>) => VNode;
+}
+export default function DepositConfirmationList({
+  onUnauthorized,
+  onLoadError,
+  onCreate,
+  onSelect,
+  onNotFound,
+}: Props): VNode {
+  const result = useDepositConfirmation();
+  const { deleteDepositConfirmation, updateDepositConfirmation, 
getDepositConfirmation } = useDepositConfirmationAPI();
+  const [deleting, setDeleting] =
+    useState<AuditorBackend.DepositConfirmation.DepositConfirmationDetail & 
WithId | null>(null);
+  const [notif, setNotif] = useState<Notification | undefined>(undefined);
+
+  const { i18n } = useTranslationContext();
+
+  if (result.loading) return <Loading />;
+  if (!result.ok) {
+    if (
+      result.type === ErrorType.CLIENT &&
+      result.status === HttpStatusCode.Unauthorized
+    )
+      return onUnauthorized();
+    if (
+      result.type === ErrorType.CLIENT &&
+      result.status === HttpStatusCode.NotFound
+    )
+      return onNotFound();
+    return onLoadError(result);
+  }
+
+  return (
+    <section class="section is-main-section">
+      <NotificationCard notification={notif} />
+
+      <JumpToElementById
+        testIfExist={getDepositConfirmation}
+        onSelect={onSelect}
+        description={i18n.str`jump to deposit_confirmation with the given 
serial ID`}
+        palceholder={i18n.str`serial id`}
+      />
+
+      <CardTable
+        instances={result.data}
+        onCreate={onCreate}
+        onUpdate={(id, prod) =>
+          updateDepositConfirmation(id, prod)
+            .then(() =>
+              setNotif({
+                message: i18n.str`deposit_confirmation updated successfully`,
+                type: "SUCCESS",
+              }),
+            )
+            .catch((error) =>
+              setNotif({
+                message: i18n.str`could not update the deposit_confirmation`,
+                type: "ERROR",
+                description: error.message,
+              }),
+            )
+        }
+        onSelect={(depositConfirmation) => onSelect(depositConfirmation.id)}
+        onDelete={(depositConfirmation : 
AuditorBackend.DepositConfirmation.DepositConfirmationDetail & WithId) =>
+          setDeleting(depositConfirmation)
+        }
+      />
+
+      {deleting && (
+        <ConfirmModal
+          label={`Delete deposit-confirmation`}
+          description={`Delete the deposit-cofirmation 
"${deleting.serial_id}"`}
+          danger
+          active
+          onCancel={() => setDeleting(null)}
+          onConfirm={async (): Promise<void> => {
+            try {
+              await deleteDepositConfirmation(deleting.serial_id);
+              setNotif({
+                message: i18n.str`Deposit-confirmation "${deleting.serial_id}" 
(ID: ${deleting.serial_id}) has been deleted`,
+                type: "SUCCESS",
+              });
+            } catch (error) {
+              setNotif({
+                message: i18n.str`Failed to delete deposit-confirmation`,
+                type: "ERROR",
+                description: error instanceof Error ? error.message : 
undefined,
+              });
+            }
+            setDeleting(null);
+          }}
+        >
+          <p>
+            If you delete the deposit-confirmation (ID:{" "}
+            <b>{deleting.serial_id}</b>), the stock and related information 
will be lost
+          </p>
+          <p class="warning">
+            Deleting a deposit-confirmation <b>cannot be undone</b>.
+          </p>
+        </ConfirmModal>
+      )}
+    </section>
+  );
+}
diff --git 
a/packages/auditor-backoffice-ui/src/paths/instance/deposit_confirmations/update/Update.stories.tsx
 
b/packages/auditor-backoffice-ui/src/paths/instance/deposit_confirmations/update/Update.stories.tsx
new file mode 100644
index 000000000..a85b13b8b
--- /dev/null
+++ 
b/packages/auditor-backoffice-ui/src/paths/instance/deposit_confirmations/update/Update.stories.tsx
@@ -0,0 +1,73 @@
+/*
+ This file is part of GNU Taler
+ (C) 2021-2023 Taler Systems S.A.
+
+ GNU Taler is free software; you can redistribute it and/or modify it under the
+ terms of the GNU General Public License as published by the Free Software
+ Foundation; either version 3, or (at your option) any later version.
+
+ GNU Taler is distributed in the hope that it will be useful, but WITHOUT ANY
+ WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
+ A PARTICULAR PURPOSE.  See the GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License along with
+ GNU Taler; see the file COPYING.  If not, see <http://www.gnu.org/licenses/>
+ */
+
+/**
+ *
+ * @author Sebastian Javier Marchano (sebasjm)
+ */
+
+import { h, VNode, FunctionalComponent } from "preact";
+import { UpdatePage as TestedComponent } from "./UpdatePage.js";
+
+export default {
+  title: "Pages/Product/Update",
+  component: TestedComponent,
+  argTypes: {
+    onUpdate: { action: "onUpdate" },
+    onBack: { action: "onBack" },
+  },
+};
+
+function createExample<Props>(
+  Component: FunctionalComponent<Props>,
+  props: Partial<Props>,
+) {
+  const r = (args: any) => <Component {...args} />;
+  r.args = props;
+  return r;
+}
+
+export const WithManagedStock = createExample(TestedComponent, {
+  product: {
+    product_id: "20102-ASDAS-QWE",
+    description: "description1",
+    description_i18n: {} as any,
+    image: "",
+    price: "TESTKUDOS:10",
+    taxes: [],
+    total_lost: 10,
+    total_sold: 5,
+    total_stock: 15,
+    unit: "bar",
+    address: {},
+  },
+});
+
+export const WithInfiniteStock = createExample(TestedComponent, {
+  product: {
+    product_id: "20102-ASDAS-QWE",
+    description: "description1",
+    description_i18n: {} as any,
+    image: "",
+    price: "TESTKUDOS:10",
+    taxes: [],
+    total_lost: 10,
+    total_sold: 5,
+    total_stock: -1,
+    unit: "bar",
+    address: {},
+  },
+});
diff --git 
a/packages/auditor-backoffice-ui/src/paths/instance/deposit_confirmations/update/UpdatePage.tsx
 
b/packages/auditor-backoffice-ui/src/paths/instance/deposit_confirmations/update/UpdatePage.tsx
new file mode 100644
index 000000000..97715171e
--- /dev/null
+++ 
b/packages/auditor-backoffice-ui/src/paths/instance/deposit_confirmations/update/UpdatePage.tsx
@@ -0,0 +1,99 @@
+/*
+ This file is part of GNU Taler
+ (C) 2021-2023 Taler Systems S.A.
+
+ GNU Taler is free software; you can redistribute it and/or modify it under the
+ terms of the GNU General Public License as published by the Free Software
+ Foundation; either version 3, or (at your option) any later version.
+
+ GNU Taler is distributed in the hope that it will be useful, but WITHOUT ANY
+ WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
+ A PARTICULAR PURPOSE.  See the GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License along with
+ GNU Taler; see the file COPYING.  If not, see <http://www.gnu.org/licenses/>
+ */
+
+/**
+ *
+ * @author Sebastian Javier Marchano (sebasjm)
+ */
+
+import { useTranslationContext } from "@gnu-taler/web-util/browser";
+import { h, VNode } from "preact";
+import { AsyncButton } from "../../../../components/exception/AsyncButton.js";
+import { ProductForm } from "../../../../components/product/ProductForm.js";
+import { MerchantBackend } from "../../../../declaration.js";
+import { useListener } from "../../../../hooks/listener.js";
+
+type Entity = MerchantBackend.Products.ProductDetail & { product_id: string };
+
+interface Props {
+  onUpdate: (d: Entity) => Promise<void>;
+  onBack?: () => void;
+  product: Entity;
+}
+
+export function UpdatePage({ product, onUpdate, onBack }: Props): VNode {
+  const [submitForm, addFormSubmitter] = useListener<Entity | undefined>(
+    (result) => {
+      if (result) return onUpdate(result);
+      return Promise.resolve();
+    },
+  );
+
+  const { i18n } = useTranslationContext();
+
+  return (
+    <div>
+      <section class="section">
+        <section class="hero is-hero-bar">
+          <div class="hero-body">
+            <div class="level">
+              <div class="level-left">
+                <div class="level-item">
+                  <span class="is-size-4">
+                    <i18n.Translate>Product id:</i18n.Translate>
+                    <b>{product.product_id}</b>
+                  </span>
+                </div>
+              </div>
+            </div>
+          </div>
+        </section>
+        <hr />
+
+        <div class="columns">
+          <div class="column" />
+          <div class="column is-four-fifths">
+            <ProductForm
+              initial={product}
+              onSubscribe={addFormSubmitter}
+              alreadyExist
+            />
+
+            <div class="buttons is-right mt-5">
+              {onBack && (
+                <button class="button" onClick={onBack}>
+                  <i18n.Translate>Cancel</i18n.Translate>
+                </button>
+              )}
+              <AsyncButton
+                onClick={submitForm}
+                data-tooltip={
+                  !submitForm
+                    ? i18n.str`Need to complete marked fields`
+                    : "confirm operation"
+                }
+                disabled={!submitForm}
+              >
+                <i18n.Translate>Confirm</i18n.Translate>
+              </AsyncButton>
+            </div>
+          </div>
+          <div class="column" />
+        </div>
+      </section>
+    </div>
+  );
+}
diff --git 
a/packages/auditor-backoffice-ui/src/paths/instance/deposit_confirmations/update/index.tsx
 
b/packages/auditor-backoffice-ui/src/paths/instance/deposit_confirmations/update/index.tsx
new file mode 100644
index 000000000..8e0f7647f
--- /dev/null
+++ 
b/packages/auditor-backoffice-ui/src/paths/instance/deposit_confirmations/update/index.tsx
@@ -0,0 +1,95 @@
+/*
+ This file is part of GNU Taler
+ (C) 2021-2023 Taler Systems S.A.
+
+ GNU Taler is free software; you can redistribute it and/or modify it under the
+ terms of the GNU General Public License as published by the Free Software
+ Foundation; either version 3, or (at your option) any later version.
+
+ GNU Taler is distributed in the hope that it will be useful, but WITHOUT ANY
+ WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
+ A PARTICULAR PURPOSE.  See the GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License along with
+ GNU Taler; see the file COPYING.  If not, see <http://www.gnu.org/licenses/>
+ */
+
+/**
+ *
+ * @author Sebastian Javier Marchano (sebasjm)
+ */
+
+import {
+  ErrorType,
+  HttpError,
+  useTranslationContext,
+} from "@gnu-taler/web-util/browser";
+import { Fragment, h, VNode } from "preact";
+import { useState } from "preact/hooks";
+import { Loading } from "../../../../components/exception/loading.js";
+import { NotificationCard } from "../../../../components/menu/index.js";
+import { MerchantBackend } from "../../../../declaration.js";
+import { useProductAPI, useProductDetails } from 
"../../../../hooks/product.js";
+import { Notification } from "../../../../utils/types.js";
+import { UpdatePage } from "./UpdatePage.js";
+import { HttpStatusCode } from "@gnu-taler/taler-util";
+
+export type Entity = MerchantBackend.Products.ProductAddDetail;
+interface Props {
+  onBack?: () => void;
+  onConfirm: () => void;
+  onUnauthorized: () => VNode;
+  onNotFound: () => VNode;
+  onLoadError: (e: HttpError<MerchantBackend.ErrorDetail>) => VNode;
+  pid: string;
+}
+export default function UpdateProduct({
+  pid,
+  onConfirm,
+  onBack,
+  onUnauthorized,
+  onNotFound,
+  onLoadError,
+}: Props): VNode {
+  const { updateProduct } = useProductAPI();
+  const result = useProductDetails(pid);
+  const [notif, setNotif] = useState<Notification | undefined>(undefined);
+
+  const { i18n } = useTranslationContext();
+
+  if (result.loading) return <Loading />;
+  if (!result.ok) {
+    if (
+      result.type === ErrorType.CLIENT &&
+      result.status === HttpStatusCode.Unauthorized
+    )
+      return onUnauthorized();
+    if (
+      result.type === ErrorType.CLIENT &&
+      result.status === HttpStatusCode.NotFound
+    )
+      return onNotFound();
+    return onLoadError(result);
+  }
+
+  return (
+    <Fragment>
+      <NotificationCard notification={notif} />
+      <UpdatePage
+        product={{ ...result.data, product_id: pid }}
+        onBack={onBack}
+        onUpdate={(data) => {
+          return updateProduct(pid, data)
+            .then(onConfirm)
+            .catch((error) => {
+              setNotif({
+                message: i18n.str`could not create product`,
+                type: "ERROR",
+                description: error.message,
+              });
+            });
+        }}
+      />
+    </Fragment>
+  );
+}
diff --git 
a/packages/auditor-backoffice-ui/src/paths/instance/details/DetailPage.tsx 
b/packages/auditor-backoffice-ui/src/paths/instance/details/DetailPage.tsx
new file mode 100644
index 000000000..21dadb1e3
--- /dev/null
+++ b/packages/auditor-backoffice-ui/src/paths/instance/details/DetailPage.tsx
@@ -0,0 +1,83 @@
+/*
+ This file is part of GNU Taler
+ (C) 2021-2023 Taler Systems S.A.
+
+ GNU Taler is free software; you can redistribute it and/or modify it under the
+ terms of the GNU General Public License as published by the Free Software
+ Foundation; either version 3, or (at your option) any later version.
+
+ GNU Taler is distributed in the hope that it will be useful, but WITHOUT ANY
+ WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
+ A PARTICULAR PURPOSE.  See the GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License along with
+ GNU Taler; see the file COPYING.  If not, see <http://www.gnu.org/licenses/>
+ */
+
+/**
+ *
+ * @author Sebastian Javier Marchano (sebasjm)
+ */
+
+import { useTranslationContext } from "@gnu-taler/web-util/browser";
+import { h, VNode } from "preact";
+import { useState } from "preact/hooks";
+import { FormProvider } from "../../../components/form/FormProvider.js";
+import { Input } from "../../../components/form/Input.js";
+import { MerchantBackend } from "../../../declaration.js";
+
+type Entity = MerchantBackend.Instances.InstanceReconfigurationMessage;
+interface Props {
+  onUpdate: () => void;
+  onDelete: () => void;
+  selected: MerchantBackend.Instances.QueryInstancesResponse;
+}
+
+function convert(
+  from: MerchantBackend.Instances.QueryInstancesResponse,
+): Entity {
+  const defaults = {
+    default_wire_fee_amortization: 1,
+    use_stefan: true,
+    default_pay_delay: { d_us: 1000 * 60 * 60 * 1000 }, //one hour
+    default_wire_transfer_delay: { d_us: 1000 * 60 * 60 * 2 * 1000 }, //two 
hours
+  };
+  return { ...defaults, ...from };
+}
+
+export function DetailPage({ selected }: Props): VNode {
+  const [value, valueHandler] = useState<Partial<Entity>>(convert(selected));
+
+  const { i18n } = useTranslationContext();
+
+  return (
+    <div>
+      <section class="hero is-hero-bar">
+        <div class="hero-body">
+          <div class="level">
+            <div class="level-left">
+              <div class="level-item">
+                <h1 class="title">Here goes the instance description</h1>
+              </div>
+            </div>
+            <div class="level-right" style="display: none;">
+              <div class="level-item" />
+            </div>
+          </div>
+        </div>
+      </section>
+
+      <section class="section is-main-section">
+        <div class="columns">
+          <div class="column" />
+          <div class="column is-6">
+            <FormProvider<Entity> object={value} valueHandler={valueHandler}>
+              <Input<Entity> name="name" readonly label={i18n.str`Name`} />
+            </FormProvider>
+          </div>
+          <div class="column" />
+        </div>
+      </section>
+    </div>
+  );
+}
diff --git 
a/packages/auditor-backoffice-ui/src/paths/instance/details/index.tsx 
b/packages/auditor-backoffice-ui/src/paths/instance/details/index.tsx
new file mode 100644
index 000000000..9b393b818
--- /dev/null
+++ b/packages/auditor-backoffice-ui/src/paths/instance/details/index.tsx
@@ -0,0 +1,87 @@
+/*
+ This file is part of GNU Taler
+ (C) 2021-2023 Taler Systems S.A.
+
+ GNU Taler is free software; you can redistribute it and/or modify it under the
+ terms of the GNU General Public License as published by the Free Software
+ Foundation; either version 3, or (at your option) any later version.
+
+ GNU Taler is distributed in the hope that it will be useful, but WITHOUT ANY
+ WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
+ A PARTICULAR PURPOSE.  See the GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License along with
+ GNU Taler; see the file COPYING.  If not, see <http://www.gnu.org/licenses/>
+ */
+import { ErrorType, HttpError } from "@gnu-taler/web-util/browser";
+import { Fragment, h, VNode } from "preact";
+import { useState } from "preact/hooks";
+import { Loading } from "../../../components/exception/loading.js";
+import { DeleteModal } from "../../../components/modal/index.js";
+import { useInstanceContext } from "../../../context/instance.js";
+import { MerchantBackend } from "../../../declaration.js";
+import { useInstanceAPI, useInstanceDetails } from 
"../../../hooks/instance.js";
+import { DetailPage } from "./DetailPage.js";
+import { HttpStatusCode } from "@gnu-taler/taler-util";
+
+interface Props {
+  onUnauthorized: () => VNode;
+  onLoadError: (error: HttpError<MerchantBackend.ErrorDetail>) => VNode;
+  onUpdate: () => void;
+  onNotFound: () => VNode;
+  onDelete: () => void;
+}
+
+export default function Detail({
+  onUpdate,
+  onLoadError,
+  onUnauthorized,
+  onDelete,
+  onNotFound,
+}: Props): VNode {
+  const { id } = useInstanceContext();
+  const result = useInstanceDetails();
+  const [deleting, setDeleting] = useState<boolean>(false);
+
+  const { deleteInstance } = useInstanceAPI();
+
+  if (result.loading) return <Loading />;
+  if (!result.ok) {
+    if (
+      result.type === ErrorType.CLIENT &&
+      result.status === HttpStatusCode.Unauthorized
+    )
+      return onUnauthorized();
+    if (
+      result.type === ErrorType.CLIENT &&
+      result.status === HttpStatusCode.NotFound
+    )
+      return onNotFound();
+    return onLoadError(result);
+  }
+
+  return (
+    <Fragment>
+      <DetailPage
+        selected={result.data}
+        onUpdate={onUpdate}
+        onDelete={() => setDeleting(true)}
+      />
+      {deleting && (
+        <DeleteModal
+          element={{ name: result.data.name, id }}
+          onCancel={() => setDeleting(false)}
+          onConfirm={async (): Promise<void> => {
+            try {
+              await deleteInstance();
+              onDelete();
+            } catch (error) {
+              //FIXME: show message error
+            }
+            setDeleting(false);
+          }}
+        />
+      )}
+    </Fragment>
+  );
+}
diff --git 
a/packages/auditor-backoffice-ui/src/paths/instance/details/stories.tsx 
b/packages/auditor-backoffice-ui/src/paths/instance/details/stories.tsx
new file mode 100644
index 000000000..367fabce2
--- /dev/null
+++ b/packages/auditor-backoffice-ui/src/paths/instance/details/stories.tsx
@@ -0,0 +1,68 @@
+/*
+ This file is part of GNU Taler
+ (C) 2021-2023 Taler Systems S.A.
+
+ GNU Taler is free software; you can redistribute it and/or modify it under the
+ terms of the GNU General Public License as published by the Free Software
+ Foundation; either version 3, or (at your option) any later version.
+
+ GNU Taler is distributed in the hope that it will be useful, but WITHOUT ANY
+ WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
+ A PARTICULAR PURPOSE.  See the GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License along with
+ GNU Taler; see the file COPYING.  If not, see <http://www.gnu.org/licenses/>
+ */
+
+/**
+ *
+ * @author Sebastian Javier Marchano (sebasjm)
+ */
+
+import { h, VNode, FunctionalComponent } from "preact";
+import { ConfigContextProvider } from "../../../context/config.js";
+import { DetailPage as TestedComponent } from "./DetailPage.js";
+
+export default {
+  title: "Pages/Instance/Detail",
+  component: TestedComponent,
+  argTypes: {
+    onUpdate: { action: "onUpdate" },
+    onBack: { action: "onBack" },
+  },
+};
+
+function createExample<Props>(
+  Internal: FunctionalComponent<Props>,
+  props: Partial<Props>,
+) {
+  const component = (args: any) => (
+    <ConfigContextProvider
+      value={{
+        currency: "TESTKUDOS",
+        version: "1",
+      }}
+    >
+      <Internal {...(props as any)} />
+    </ConfigContextProvider>
+  );
+  return { component, props };
+}
+
+export const Example = createExample(TestedComponent, {
+  selected: {
+    name: "name",
+    auth: { method: "external" },
+    address: {},
+    user_type: "business",
+    jurisdiction: {},
+    use_stefan: true,
+    default_pay_delay: {
+      d_us: 1000 * 1000, //one second
+    },
+    default_wire_transfer_delay: {
+      d_us: 1000 * 1000, //one second
+    },
+    merchant_pub: "ASDWQEKASJDKSADJ",
+  },
+});
diff --git a/packages/auditor-backoffice-ui/src/paths/instance/index.stories.ts 
b/packages/auditor-backoffice-ui/src/paths/instance/index.stories.ts
new file mode 100644
index 000000000..1d8c76ff9
--- /dev/null
+++ b/packages/auditor-backoffice-ui/src/paths/instance/index.stories.ts
@@ -0,0 +1,19 @@
+/*
+ This file is part of GNU Taler
+ (C) 2021-2023 Taler Systems S.A.
+
+ GNU Taler is free software; you can redistribute it and/or modify it under the
+ terms of the GNU General Public License as published by the Free Software
+ Foundation; either version 3, or (at your option) any later version.
+
+ GNU Taler is distributed in the hope that it will be useful, but WITHOUT ANY
+ WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
+ A PARTICULAR PURPOSE.  See the GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License along with
+ GNU Taler; see the file COPYING.  If not, see <http://www.gnu.org/licenses/>
+ */
+
+export * as details from "./details/stories.js";
+export * as kycList from "./kyc/list/ListPage.stories.js";
+export * as reserve from "./reserves/create/CreatedSuccessfully.stories.js";
diff --git 
a/packages/auditor-backoffice-ui/src/paths/instance/kyc/list/ListPage.stories.tsx
 
b/packages/auditor-backoffice-ui/src/paths/instance/kyc/list/ListPage.stories.tsx
new file mode 100644
index 000000000..d33f64ada
--- /dev/null
+++ 
b/packages/auditor-backoffice-ui/src/paths/instance/kyc/list/ListPage.stories.tsx
@@ -0,0 +1,58 @@
+/*
+ This file is part of GNU Taler
+ (C) 2021-2023 Taler Systems S.A.
+
+ GNU Taler is free software; you can redistribute it and/or modify it under the
+ terms of the GNU General Public License as published by the Free Software
+ Foundation; either version 3, or (at your option) any later version.
+
+ GNU Taler is distributed in the hope that it will be useful, but WITHOUT ANY
+ WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
+ A PARTICULAR PURPOSE.  See the GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License along with
+ GNU Taler; see the file COPYING.  If not, see <http://www.gnu.org/licenses/>
+ */
+
+/**
+ *
+ * @author Sebastian Javier Marchano (sebasjm)
+ */
+
+import { h, VNode, FunctionalComponent } from "preact";
+import { ListPage as TestedComponent } from "./ListPage.js";
+import * as tests from "@gnu-taler/web-util/testing";
+import { MerchantBackend } from "../../../../declaration.js";
+
+export default {
+  title: "Pages/KYC/List",
+  component: TestedComponent,
+  argTypes: {
+    onUpdate: { action: "onUpdate" },
+    onBack: { action: "onBack" },
+  },
+};
+
+export const Example = tests.createExample(TestedComponent, {
+  status: {
+    timeout_kycs: [],
+    pending_kycs: [
+      {
+        aml_status: 0,
+        exchange_url: "http://exchange.taler";,
+        payto_uri: "payto://iban/de123123123",
+        kyc_url: "http://exchange.taler/kyc";,
+      },
+      {
+        aml_status: 1,
+        exchange_url: "http://exchange.taler";,
+        payto_uri: "payto://iban/de123123123",
+      },
+      {
+        aml_status: 2,
+        exchange_url: "http://exchange.taler";,
+        payto_uri: "payto://iban/de123123123",
+      },
+    ],
+  } as MerchantBackend.KYC.AccountKycRedirects,
+});
diff --git 
a/packages/auditor-backoffice-ui/src/paths/instance/kyc/list/ListPage.tsx 
b/packages/auditor-backoffice-ui/src/paths/instance/kyc/list/ListPage.tsx
new file mode 100644
index 000000000..338081886
--- /dev/null
+++ b/packages/auditor-backoffice-ui/src/paths/instance/kyc/list/ListPage.tsx
@@ -0,0 +1,208 @@
+/*
+ This file is part of GNU Taler
+ (C) 2021-2023 Taler Systems S.A.
+
+ GNU Taler is free software; you can redistribute it and/or modify it under the
+ terms of the GNU General Public License as published by the Free Software
+ Foundation; either version 3, or (at your option) any later version.
+
+ GNU Taler is distributed in the hope that it will be useful, but WITHOUT ANY
+ WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
+ A PARTICULAR PURPOSE.  See the GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License along with
+ GNU Taler; see the file COPYING.  If not, see <http://www.gnu.org/licenses/>
+ */
+
+/**
+ *
+ * @author Sebastian Javier Marchano (sebasjm)
+ */
+
+import { useTranslationContext } from "@gnu-taler/web-util/browser";
+import { h, VNode } from "preact";
+import { MerchantBackend } from "../../../../declaration.js";
+
+export interface Props {
+  status: MerchantBackend.KYC.AccountKycRedirects;
+}
+
+export function ListPage({ status }: Props): VNode {
+  const { i18n } = useTranslationContext();
+
+  return (
+    <section class="section is-main-section">
+      <div class="card has-table">
+        <header class="card-header">
+          <p class="card-header-title">
+            <span class="icon">
+              <i class="mdi mdi-clock" />
+            </span>
+            <i18n.Translate>Pending KYC verification</i18n.Translate>
+          </p>
+
+          <div class="card-header-icon" aria-label="more options" />
+        </header>
+        <div class="card-content">
+          <div class="b-table has-pagination">
+            <div class="table-wrapper has-mobile-cards">
+              {status.pending_kycs.length > 0 ? (
+                <PendingTable entries={status.pending_kycs} />
+              ) : (
+                <EmptyTable />
+              )}
+            </div>
+          </div>
+        </div>
+      </div>
+
+      {status.timeout_kycs.length > 0 ? (
+        <div class="card has-table">
+          <header class="card-header">
+            <p class="card-header-title">
+              <span class="icon">
+                <i class="mdi mdi-clock" />
+              </span>
+              <i18n.Translate>Timed out</i18n.Translate>
+            </p>
+
+            <div class="card-header-icon" aria-label="more options" />
+          </header>
+          <div class="card-content">
+            <div class="b-table has-pagination">
+              <div class="table-wrapper has-mobile-cards">
+                {status.timeout_kycs.length > 0 ? (
+                  <TimedOutTable entries={status.timeout_kycs} />
+                ) : (
+                  <EmptyTable />
+                )}
+              </div>
+            </div>
+          </div>
+        </div>
+      ) : undefined}
+    </section>
+  );
+}
+interface PendingTableProps {
+  entries: MerchantBackend.KYC.MerchantAccountKycRedirect[];
+}
+
+interface TimedOutTableProps {
+  entries: MerchantBackend.KYC.ExchangeKycTimeout[];
+}
+
+function PendingTable({ entries }: PendingTableProps): VNode {
+  const { i18n } = useTranslationContext();
+  return (
+    <div class="table-container">
+      <table class="table is-striped is-hoverable is-fullwidth">
+        <thead>
+          <tr>
+            <th>
+              <i18n.Translate>Exchange</i18n.Translate>
+            </th>
+            <th>
+              <i18n.Translate>Target account</i18n.Translate>
+            </th>
+            <th>
+              <i18n.Translate>Reason</i18n.Translate>
+            </th>
+          </tr>
+        </thead>
+        <tbody>
+          {entries.map((e, i) => {
+            if (e.kyc_url === undefined) {
+              // blocked by AML
+              return (
+                <tr key={i}>
+                  <td>{e.exchange_url}</td>
+                  <td>{e.payto_uri}</td>
+                  <td>
+                    {e.aml_status === 1 ? (
+                      <i18n.Translate>
+                        There is an anti-money laundering process pending to
+                        complete.
+                      </i18n.Translate>
+                    ) : (
+                      <i18n.Translate>
+                        The account is frozen due to the anti-money laundering
+                        rules. Contact the exchange service provider for 
further
+                        instructions.
+                      </i18n.Translate>
+                    )}
+                  </td>
+                </tr>
+              );
+            } else {
+              // blocked by KYC
+              return (
+                <tr key={i}>
+                  <td>{e.exchange_url}</td>
+                  <td>{e.payto_uri}</td>
+                  <td>
+                    <a href={e.kyc_url} target="_black" rel="noreferrer">
+                      <i18n.Translate>
+                        Pending KYC process, click here to complete
+                      </i18n.Translate>
+                    </a>
+                  </td>
+                </tr>
+              );
+            }
+          })}
+        </tbody>
+      </table>
+    </div>
+  );
+}
+
+function TimedOutTable({ entries }: TimedOutTableProps): VNode {
+  const { i18n } = useTranslationContext();
+  return (
+    <div class="table-container">
+      <table class="table is-striped is-hoverable is-fullwidth">
+        <thead>
+          <tr>
+            <th>
+              <i18n.Translate>Exchange</i18n.Translate>
+            </th>
+            <th>
+              <i18n.Translate>Code</i18n.Translate>
+            </th>
+            <th>
+              <i18n.Translate>Http Status</i18n.Translate>
+            </th>
+          </tr>
+        </thead>
+        <tbody>
+          {entries.map((e, i) => {
+            return (
+              <tr key={i}>
+                <td>{e.exchange_url}</td>
+                <td>{e.exchange_code}</td>
+                <td>{e.exchange_http_status}</td>
+              </tr>
+            );
+          })}
+        </tbody>
+      </table>
+    </div>
+  );
+}
+
+function EmptyTable(): VNode {
+  const { i18n } = useTranslationContext();
+  return (
+    <div class="content has-text-grey has-text-centered">
+      <p>
+        <span class="icon is-large">
+          <i class="mdi mdi-emoticon-happy mdi-48px" />
+        </span>
+      </p>
+      <p>
+        <i18n.Translate>No pending kyc verification!</i18n.Translate>
+      </p>
+    </div>
+  );
+}
diff --git 
a/packages/auditor-backoffice-ui/src/paths/instance/kyc/list/index.tsx 
b/packages/auditor-backoffice-ui/src/paths/instance/kyc/list/index.tsx
new file mode 100644
index 000000000..5b93ac169
--- /dev/null
+++ b/packages/auditor-backoffice-ui/src/paths/instance/kyc/list/index.tsx
@@ -0,0 +1,63 @@
+/*
+ This file is part of GNU Taler
+ (C) 2021-2023 Taler Systems S.A.
+
+ GNU Taler is free software; you can redistribute it and/or modify it under the
+ terms of the GNU General Public License as published by the Free Software
+ Foundation; either version 3, or (at your option) any later version.
+
+ GNU Taler is distributed in the hope that it will be useful, but WITHOUT ANY
+ WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
+ A PARTICULAR PURPOSE.  See the GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License along with
+ GNU Taler; see the file COPYING.  If not, see <http://www.gnu.org/licenses/>
+ */
+
+/**
+ *
+ * @author Sebastian Javier Marchano (sebasjm)
+ */
+
+import { ErrorType, HttpError } from "@gnu-taler/web-util/browser";
+import { h, VNode } from "preact";
+import { Loading } from "../../../../components/exception/loading.js";
+import { MerchantBackend } from "../../../../declaration.js";
+import { useInstanceKYCDetails } from "../../../../hooks/instance.js";
+import { ListPage } from "./ListPage.js";
+import { HttpStatusCode } from "@gnu-taler/taler-util";
+
+interface Props {
+  onUnauthorized: () => VNode;
+  onLoadError: (error: HttpError<MerchantBackend.ErrorDetail>) => VNode;
+  onNotFound: () => VNode;
+}
+
+export default function ListKYC({
+  onUnauthorized,
+  onLoadError,
+  onNotFound,
+}: Props): VNode {
+  const result = useInstanceKYCDetails();
+  if (result.loading) return <Loading />;
+  if (!result.ok) {
+    if (
+      result.type === ErrorType.CLIENT &&
+      result.status === HttpStatusCode.Unauthorized
+    )
+      return onUnauthorized();
+    if (
+      result.type === ErrorType.CLIENT &&
+      result.status === HttpStatusCode.NotFound
+    )
+      return onNotFound();
+    return onLoadError(result);
+  }
+
+  const status = result.data.type === "ok" ? undefined : result.data.status;
+
+  if (!status) {
+    return <div>no kyc required</div>;
+  }
+  return <ListPage status={status} />;
+}
diff --git 
a/packages/auditor-backoffice-ui/src/paths/instance/orders/create/Create.stories.tsx
 
b/packages/auditor-backoffice-ui/src/paths/instance/orders/create/Create.stories.tsx
new file mode 100644
index 000000000..bd9f65718
--- /dev/null
+++ 
b/packages/auditor-backoffice-ui/src/paths/instance/orders/create/Create.stories.tsx
@@ -0,0 +1,71 @@
+/*
+ This file is part of GNU Taler
+ (C) 2021-2023 Taler Systems S.A.
+
+ GNU Taler is free software; you can redistribute it and/or modify it under the
+ terms of the GNU General Public License as published by the Free Software
+ Foundation; either version 3, or (at your option) any later version.
+
+ GNU Taler is distributed in the hope that it will be useful, but WITHOUT ANY
+ WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
+ A PARTICULAR PURPOSE.  See the GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License along with
+ GNU Taler; see the file COPYING.  If not, see <http://www.gnu.org/licenses/>
+ */
+
+/**
+ *
+ * @author Sebastian Javier Marchano (sebasjm)
+ */
+
+import { h, VNode, FunctionalComponent } from "preact";
+import { CreatePage as TestedComponent } from "./CreatePage.js";
+
+export default {
+  title: "Pages/Order/Create",
+  component: TestedComponent,
+  argTypes: {
+    onCreate: { action: "onCreate" },
+    goBack: { action: "goBack" },
+  },
+};
+
+function createExample<Props>(
+  Component: FunctionalComponent<Props>,
+  props: Partial<Props>,
+) {
+  const r = (args: any) => <Component {...args} />;
+  r.args = props;
+  return r;
+}
+
+export const Example = createExample(TestedComponent, {
+  instanceConfig: {
+    default_pay_delay: {
+      d_us: 1000 * 1000 * 60 * 60, //one hour
+    },
+    default_wire_transfer_delay: {
+      d_us: 1000 * 1000 * 60 * 60, //one hour
+    },
+    use_stefan: true,
+  },
+  instanceInventory: [
+    {
+      id: "t-shirt-1",
+      description: "a m size t-shirt",
+      price: "TESTKUDOS:1",
+      total_stock: -1,
+    },
+    {
+      id: "t-shirt-2",
+      price: "TESTKUDOS:1",
+      description: "a xl size t-shirt",
+    } as any,
+    {
+      id: "t-shirt-3",
+      price: "TESTKUDOS:1",
+      description: "a s size t-shirt",
+    } as any,
+  ],
+});
diff --git 
a/packages/auditor-backoffice-ui/src/paths/instance/orders/create/CreatePage.tsx
 
b/packages/auditor-backoffice-ui/src/paths/instance/orders/create/CreatePage.tsx
new file mode 100644
index 000000000..fbfd023c1
--- /dev/null
+++ 
b/packages/auditor-backoffice-ui/src/paths/instance/orders/create/CreatePage.tsx
@@ -0,0 +1,705 @@
+/*
+ This file is part of GNU Taler
+ (C) 2021-2023 Taler Systems S.A.
+
+ GNU Taler is free software; you can redistribute it and/or modify it under the
+ terms of the GNU General Public License as published by the Free Software
+ Foundation; either version 3, or (at your option) any later version.
+
+ GNU Taler is distributed in the hope that it will be useful, but WITHOUT ANY
+ WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
+ A PARTICULAR PURPOSE.  See the GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License along with
+ GNU Taler; see the file COPYING.  If not, see <http://www.gnu.org/licenses/>
+ */
+
+/**
+ *
+ * @author Sebastian Javier Marchano (sebasjm)
+ */
+
+import { AbsoluteTime, Amounts, Duration, TalerProtocolDuration } from 
"@gnu-taler/taler-util";
+import { useTranslationContext } from "@gnu-taler/web-util/browser";
+import { format, isFuture } from "date-fns";
+import { ComponentChildren, Fragment, VNode, h } from "preact";
+import { useEffect, useState } from "preact/hooks";
+import {
+  FormErrors,
+  FormProvider,
+} from "../../../../components/form/FormProvider.js";
+import { Input } from "../../../../components/form/Input.js";
+import { InputCurrency } from "../../../../components/form/InputCurrency.js";
+import { InputDate } from "../../../../components/form/InputDate.js";
+import { InputDuration } from "../../../../components/form/InputDuration.js";
+import { InputGroup } from "../../../../components/form/InputGroup.js";
+import { InputLocation } from "../../../../components/form/InputLocation.js";
+import { InputNumber } from "../../../../components/form/InputNumber.js";
+import { InputToggle } from "../../../../components/form/InputToggle.js";
+import { InventoryProductForm } from 
"../../../../components/product/InventoryProductForm.js";
+import { NonInventoryProductFrom } from 
"../../../../components/product/NonInventoryProductForm.js";
+import { ProductList } from "../../../../components/product/ProductList.js";
+import { useConfigContext } from "../../../../context/config.js";
+import { MerchantBackend, WithId } from "../../../../declaration.js";
+import { useSettings } from "../../../../hooks/useSettings.js";
+import { OrderCreateSchema as schema } from "../../../../schemas/index.js";
+import { rate } from "../../../../utils/amount.js";
+import { undefinedIfEmpty } from "../../../../utils/table.js";
+
+interface Props {
+  onCreate: (d: MerchantBackend.Orders.PostOrderRequest) => void;
+  onBack?: () => void;
+  instanceConfig: InstanceConfig;
+  instanceInventory: (MerchantBackend.Products.ProductDetail & WithId)[];
+}
+interface InstanceConfig {
+  use_stefan: boolean;
+  default_pay_delay: TalerProtocolDuration;
+  default_wire_transfer_delay: TalerProtocolDuration;
+}
+
+function with_defaults(config: InstanceConfig, currency: string): 
Partial<Entity> {
+  const defaultPayDeadline = 
Duration.fromTalerProtocolDuration(config.default_pay_delay);
+  const defaultWireDeadline = 
Duration.fromTalerProtocolDuration(config.default_wire_transfer_delay);
+
+  return {
+    inventoryProducts: {},
+    products: [],
+    pricing: {},
+    payments: {
+      max_fee: undefined,
+      createToken: true,
+      pay_deadline: (defaultPayDeadline),
+      refund_deadline: (defaultPayDeadline),
+      wire_transfer_deadline: (defaultWireDeadline),
+    },
+    shipping: {},
+    extra: {},
+  };
+}
+
+interface ProductAndQuantity {
+  product: MerchantBackend.Products.ProductDetail & WithId;
+  quantity: number;
+}
+export interface ProductMap {
+  [id: string]: ProductAndQuantity;
+}
+
+interface Pricing {
+  products_price: string;
+  order_price: string;
+  summary: string;
+}
+interface Shipping {
+  delivery_date?: Date;
+  delivery_location?: MerchantBackend.Location;
+  fullfilment_url?: string;
+}
+interface Payments {
+  refund_deadline: Duration;
+  pay_deadline: Duration;
+  wire_transfer_deadline: Duration;
+  auto_refund_deadline: Duration;
+  max_fee?: string;
+  createToken: boolean;
+  minimum_age?: number;
+}
+interface Entity {
+  inventoryProducts: ProductMap;
+  products: MerchantBackend.Product[];
+  pricing: Partial<Pricing>;
+  payments: Partial<Payments>;
+  shipping: Partial<Shipping>;
+  extra: Record<string, string>;
+}
+
+const stringIsValidJSON = (value: string) => {
+  try {
+    JSON.parse(value.trim());
+    return true;
+  } catch {
+    return false;
+  }
+};
+
+export function CreatePage({
+  onCreate,
+  onBack,
+  instanceConfig,
+  instanceInventory,
+}: Props): VNode {
+  const config = useConfigContext();
+  const instance_default = with_defaults(instanceConfig, config.currency)
+  const [value, valueHandler] = useState(instance_default);
+  const zero = Amounts.zeroOfCurrency(config.currency);
+  const [settings, updateSettings] = useSettings()
+  const inventoryList = Object.values(value.inventoryProducts || {});
+  const productList = Object.values(value.products || {});
+
+  const { i18n } = useTranslationContext();
+
+  const parsedPrice = !value.pricing?.order_price
+    ? undefined
+    : Amounts.parse(value.pricing.order_price);
+
+  const errors: FormErrors<Entity> = {
+    pricing: undefinedIfEmpty({
+      summary: !value.pricing?.summary ? i18n.str`required` : undefined,
+      order_price: !value.pricing?.order_price
+        ? i18n.str`required`
+        : !parsedPrice
+          ? i18n.str`not valid`
+          : Amounts.isZero(parsedPrice)
+            ? i18n.str`must be greater than 0`
+            : undefined,
+    }),
+    payments: undefinedIfEmpty({
+      refund_deadline: !value.payments?.refund_deadline
+        ? undefined
+        : value.payments.pay_deadline &&
+          Duration.cmp(value.payments.refund_deadline, 
value.payments.pay_deadline) === -1
+          ? i18n.str`refund deadline cannot be before pay deadline`
+          : value.payments.wire_transfer_deadline &&
+            Duration.cmp(
+              value.payments.wire_transfer_deadline,
+              value.payments.refund_deadline,
+            ) === -1
+            ? i18n.str`wire transfer deadline cannot be before refund deadline`
+            : undefined,
+      pay_deadline: !value.payments?.pay_deadline
+        ? i18n.str`required`
+        : value.payments.wire_transfer_deadline &&
+          Duration.cmp(
+            value.payments.wire_transfer_deadline,
+            value.payments.pay_deadline,
+          ) === -1
+          ? i18n.str`wire transfer deadline cannot be before pay deadline`
+          : undefined,
+      wire_transfer_deadline: !value.payments?.wire_transfer_deadline
+        ? i18n.str`required`
+        : undefined,
+      auto_refund_deadline: !value.payments?.auto_refund_deadline
+        ? undefined
+        : !value.payments?.refund_deadline
+          ? i18n.str`should have a refund deadline`
+          : Duration.cmp(
+            value.payments.refund_deadline,
+            value.payments.auto_refund_deadline,
+          ) == -1
+            ? i18n.str`auto refund cannot be after refund deadline`
+            : undefined,
+
+    }),
+    shipping: undefinedIfEmpty({
+      delivery_date: !value.shipping?.delivery_date
+        ? undefined
+        : !isFuture(value.shipping.delivery_date)
+          ? i18n.str`should be in the future`
+          : undefined,
+    }),
+  };
+  const hasErrors = Object.keys(errors).some(
+    (k) => (errors as any)[k] !== undefined,
+  );
+
+  const submit = (): void => {
+    const order = value as any; //schema.cast(value);
+    if (!value.payments) return;
+    if (!value.shipping) return;
+
+    const request: MerchantBackend.Orders.PostOrderRequest = {
+      order: {
+        amount: order.pricing.order_price,
+        summary: order.pricing.summary,
+        products: productList,
+        extra: undefinedIfEmpty(value.extra),
+        pay_deadline: !value.payments.pay_deadline ?
+          i18n.str`required` :
+          
AbsoluteTime.toProtocolTimestamp(AbsoluteTime.addDuration(AbsoluteTime.now(), 
value.payments.pay_deadline))
+        ,// : undefined,
+        wire_transfer_deadline: value.payments.wire_transfer_deadline
+          ? 
AbsoluteTime.toProtocolTimestamp(AbsoluteTime.addDuration(AbsoluteTime.now(), 
value.payments.wire_transfer_deadline))
+          : undefined,
+        refund_deadline: value.payments.refund_deadline
+          ? 
AbsoluteTime.toProtocolTimestamp(AbsoluteTime.addDuration(AbsoluteTime.now(), 
value.payments.refund_deadline))
+          : undefined,
+        auto_refund: value.payments.auto_refund_deadline
+          ? 
Duration.toTalerProtocolDuration(value.payments.auto_refund_deadline)
+          : undefined,
+        max_fee: value.payments.max_fee as string,
+
+        delivery_date: value.shipping.delivery_date
+          ? { t_s: value.shipping.delivery_date.getTime() / 1000 }
+          : undefined,
+        delivery_location: value.shipping.delivery_location,
+        fulfillment_url: value.shipping.fullfilment_url,
+        minimum_age: value.payments.minimum_age,
+      },
+      inventory_products: inventoryList.map((p) => ({
+        product_id: p.product.id,
+        quantity: p.quantity,
+      })),
+      create_token: value.payments.createToken,
+    };
+
+    onCreate(request);
+  };
+
+  const addProductToTheInventoryList = (
+    product: MerchantBackend.Products.ProductDetail & WithId,
+    quantity: number,
+  ) => {
+    valueHandler((v) => {
+      const inventoryProducts = { ...v.inventoryProducts };
+      inventoryProducts[product.id] = { product, quantity };
+      return { ...v, inventoryProducts };
+    });
+  };
+
+  const removeProductFromTheInventoryList = (id: string) => {
+    valueHandler((v) => {
+      const inventoryProducts = { ...v.inventoryProducts };
+      delete inventoryProducts[id];
+      return { ...v, inventoryProducts };
+    });
+  };
+
+  const addNewProduct = async (product: MerchantBackend.Product) => {
+    return valueHandler((v) => {
+      const products = v.products ? [...v.products, product] : [];
+      return { ...v, products };
+    });
+  };
+
+  const removeFromNewProduct = (index: number) => {
+    valueHandler((v) => {
+      const products = v.products ? [...v.products] : [];
+      products.splice(index, 1);
+      return { ...v, products };
+    });
+  };
+
+  const [editingProduct, setEditingProduct] = useState<
+    MerchantBackend.Product | undefined
+  >(undefined);
+
+  const totalPriceInventory = inventoryList.reduce((prev, cur) => {
+    const p = Amounts.parseOrThrow(cur.product.price);
+    return Amounts.add(prev, Amounts.mult(p, cur.quantity).amount).amount;
+  }, zero);
+
+  const totalPriceProducts = productList.reduce((prev, cur) => {
+    if (!cur.price) return zero;
+    const p = Amounts.parseOrThrow(cur.price);
+    return Amounts.add(prev, Amounts.mult(p, cur.quantity).amount).amount;
+  }, zero);
+
+  const hasProducts = inventoryList.length > 0 || productList.length > 0;
+  const totalPrice = Amounts.add(totalPriceInventory, totalPriceProducts);
+
+  const totalAsString = Amounts.stringify(totalPrice.amount);
+  const allProducts = productList.concat(inventoryList.map(asProduct));
+
+  const [newField, setNewField] = useState("")
+
+  useEffect(() => {
+    valueHandler((v) => {
+      return {
+        ...v,
+        pricing: {
+          ...v.pricing,
+          products_price: hasProducts ? totalAsString : undefined,
+          order_price: hasProducts ? totalAsString : undefined,
+        },
+      };
+    });
+  }, [hasProducts, totalAsString]);
+
+  const discountOrRise = rate(
+    parsedPrice ?? Amounts.zeroOfCurrency(config.currency),
+    totalPrice.amount,
+  );
+
+  const minAgeByProducts = allProducts.reduce(
+    (cur, prev) =>
+      !prev.minimum_age || cur > prev.minimum_age ? cur : prev.minimum_age,
+    0,
+  );
+
+  // if there is no default pay deadline
+  const noDefault_payDeadline = !instance_default.payments || 
!instance_default.payments.pay_deadline
+  // and there is no defailt wire deadline
+  const noDefault_wireDeadline = !instance_default.payments || 
!instance_default.payments.wire_transfer_deadline
+  // user required to set the taler options
+  const requiresSomeTalerOptions = noDefault_payDeadline || 
noDefault_wireDeadline
+
+
+  return (
+    <div>
+
+      <section class="section is-main-section">
+        <div class="tabs is-toggle is-fullwidth is-small">
+          <ul>
+            <li class={!settings.advanceOrderMode ? "is-active" : ""} 
onClick={() => {
+              updateSettings({
+                ...settings,
+                advanceOrderMode: false
+              })
+            }}>
+              <a >
+                <span><i18n.Translate>Simple</i18n.Translate></span>
+              </a>
+            </li>
+            <li class={settings.advanceOrderMode ? "is-active" : ""} 
onClick={() => {
+              updateSettings({
+                ...settings,
+                advanceOrderMode: true
+              })
+            }}>
+              <a >
+                <span><i18n.Translate>Advanced</i18n.Translate></span>
+              </a>
+            </li>
+          </ul>
+        </div>
+        <div class="columns">
+          <div class="column" />
+          <div class="column is-four-fifths">
+            {/* // FIXME: translating plural singular */}
+            <InputGroup
+              name="inventory_products"
+              label={i18n.str`Manage products in order`}
+              alternative={
+                allProducts.length > 0 && (
+                  <p>
+                    {allProducts.length} products with a total price of{" "}
+                    {totalAsString}.
+                  </p>
+                )
+              }
+              tooltip={i18n.str`Manage list of products in the order.`}
+            >
+              <InventoryProductForm
+                currentProducts={value.inventoryProducts || {}}
+                onAddProduct={addProductToTheInventoryList}
+                inventory={instanceInventory}
+              />
+
+              {settings.advanceOrderMode &&
+                <NonInventoryProductFrom
+                  productToEdit={editingProduct}
+                  onAddProduct={(p) => {
+                    setEditingProduct(undefined);
+                    return addNewProduct(p);
+                  }}
+                />
+              }
+
+              {allProducts.length > 0 && (
+                <ProductList
+                  list={allProducts}
+                  actions={[
+                    {
+                      name: i18n.str`Remove`,
+                      tooltip: i18n.str`Remove this product from the order.`,
+                      handler: (e, index) => {
+                        if (e.product_id) {
+                          removeProductFromTheInventoryList(e.product_id);
+                        } else {
+                          removeFromNewProduct(index);
+                          setEditingProduct(e);
+                        }
+                      },
+                    },
+                  ]}
+                />
+              )}
+            </InputGroup>
+
+            <FormProvider<Entity>
+              errors={errors}
+              object={value}
+              valueHandler={valueHandler as any}
+            >
+              {hasProducts ? (
+                <Fragment>
+                  <InputCurrency
+                    name="pricing.products_price"
+                    label={i18n.str`Total price`}
+                    readonly
+                    tooltip={i18n.str`total product price added up`}
+                  />
+                  <InputCurrency
+                    name="pricing.order_price"
+                    label={i18n.str`Total price`}
+                    addonAfter={
+                      discountOrRise > 0 &&
+                      (discountOrRise < 1
+                        ? `discount of %${Math.round(
+                          (1 - discountOrRise) * 100,
+                        )}`
+                        : `rise of %${Math.round((discountOrRise - 1) * 100)}`)
+                    }
+                    tooltip={i18n.str`Amount to be paid by the customer`}
+                  />
+                </Fragment>
+              ) : (
+                <InputCurrency
+                  name="pricing.order_price"
+                  label={i18n.str`Order price`}
+                  tooltip={i18n.str`final order price`}
+                />
+              )}
+
+              <Input
+                name="pricing.summary"
+                inputType="multiline"
+                label={i18n.str`Summary`}
+                tooltip={i18n.str`Title of the order to be shown to the 
customer`}
+              />
+
+              {settings.advanceOrderMode &&
+                <InputGroup
+                  name="shipping"
+                  label={i18n.str`Shipping and Fulfillment`}
+                  initialActive
+                >
+                  <InputDate
+                    name="shipping.delivery_date"
+                    label={i18n.str`Delivery date`}
+                    tooltip={i18n.str`Deadline for physical delivery assured 
by the merchant.`}
+                  />
+                  {value.shipping?.delivery_date && (
+                    <InputGroup
+                      name="shipping.delivery_location"
+                      label={i18n.str`Location`}
+                      tooltip={i18n.str`address where the products will be 
delivered`}
+                    >
+                      <InputLocation name="shipping.delivery_location" />
+                    </InputGroup>
+                  )}
+                  <Input
+                    name="shipping.fullfilment_url"
+                    label={i18n.str`Fulfillment URL`}
+                    tooltip={i18n.str`URL to which the user will be redirected 
after successful payment.`}
+                  />
+                </InputGroup>
+              }
+
+              {(settings.advanceOrderMode || requiresSomeTalerOptions) &&
+                <InputGroup
+                  name="payments"
+                  label={i18n.str`Taler payment options`}
+                  tooltip={i18n.str`Override default Taler payment settings 
for this order`}
+                >
+                  {(settings.advanceOrderMode || noDefault_payDeadline) && 
<InputDuration
+                    name="payments.pay_deadline"
+                    label={i18n.str`Payment time`}
+                    help={<DeadlineHelp 
duration={value.payments?.pay_deadline} />}
+                    withForever
+                    withoutClear
+                    tooltip={i18n.str`Time for the customer to pay for the 
offer before it expires. Inventory products will be reserved until this 
deadline. Time start to run after the order is created.`}
+                    side={
+                      <span>
+                        <button class="button" onClick={() => {
+                          const c = {
+                            ...value,
+                            payments: {
+                              ...(value.payments ?? {}),
+                              pay_deadline: 
instance_default.payments?.pay_deadline
+                            }
+                          }
+                          valueHandler(c)
+                        }}>
+                          <i18n.Translate>default</i18n.Translate>
+                        </button>
+                      </span>
+                    }
+                  />}
+                  {settings.advanceOrderMode && <InputDuration
+                    name="payments.refund_deadline"
+                    label={i18n.str`Refund time`}
+                    help={<DeadlineHelp 
duration={value.payments?.refund_deadline} />}
+                    withForever
+                    withoutClear
+                    tooltip={i18n.str`Time while the order can be refunded by 
the merchant. Time starts after the order is created.`}
+                    side={
+                      <span>
+                        <button class="button" onClick={() => {
+                          valueHandler({
+                            ...value,
+                            payments: {
+                              ...(value.payments ?? {}),
+                              refund_deadline: 
instance_default.payments?.refund_deadline
+                            }
+                          })
+                        }}>
+                          <i18n.Translate>default</i18n.Translate>
+                        </button>
+                      </span>
+                    }
+                  />}
+                  {(settings.advanceOrderMode || noDefault_wireDeadline) && 
<InputDuration
+                    name="payments.wire_transfer_deadline"
+                    label={i18n.str`Wire transfer time`}
+                    help={<DeadlineHelp 
duration={value.payments?.wire_transfer_deadline} />}
+                    withoutClear
+                    withForever
+                    tooltip={i18n.str`Time for the exchange to make the wire 
transfer. Time starts after the order is created.`}
+                    side={
+                      <span>
+                        <button class="button" onClick={() => {
+                          valueHandler({
+                            ...value,
+                            payments: {
+                              ...(value.payments ?? {}),
+                              wire_transfer_deadline: 
instance_default.payments?.wire_transfer_deadline
+                            }
+                          })
+                        }}>
+                          <i18n.Translate>default</i18n.Translate>
+                        </button>
+                      </span>
+                    }
+                  />}
+                  {settings.advanceOrderMode && <InputDuration
+                    name="payments.auto_refund_deadline"
+                    label={i18n.str`Auto-refund time`}
+                    help={<DeadlineHelp 
duration={value.payments?.auto_refund_deadline} />}
+                    tooltip={i18n.str`Time until which the wallet will 
automatically check for refunds without user interaction.`}
+                    withForever
+                  />}
+
+                  {settings.advanceOrderMode && <InputCurrency
+                    name="payments.max_fee"
+                    label={i18n.str`Maximum fee`}
+                    tooltip={i18n.str`Maximum fees the merchant is willing to 
cover for this order. Higher deposit fees must be covered in full by the 
consumer.`}
+                  />}
+                  {settings.advanceOrderMode && <InputToggle
+                    name="payments.createToken"
+                    label={i18n.str`Create token`}
+                    tooltip={i18n.str`If the order ID is easy to guess the 
token will prevent user to steal orders from others.`}
+                  />}
+                  {settings.advanceOrderMode && <InputNumber
+                    name="payments.minimum_age"
+                    label={i18n.str`Minimum age required`}
+                    tooltip={i18n.str`Any value greater than 0 will limit the 
coins able be used to pay this contract. If empty the age restriction will be 
defined by the products`}
+                    help={
+                      minAgeByProducts > 0
+                        ? i18n.str`Min age defined by the producs is 
${minAgeByProducts}`
+                        : i18n.str`No product with age restriction in this 
order`
+                    }
+                  />}
+                </InputGroup>
+              }
+
+              {settings.advanceOrderMode &&
+                <InputGroup
+                  name="extra"
+                  label={i18n.str`Additional information`}
+                  tooltip={i18n.str`Custom information to be included in the 
contract for this order.`}
+                >
+                  {Object.keys(value.extra ?? {}).map((key) => {
+
+                    return <Input
+                      name={`extra.${key}`}
+                      inputType="multiline"
+                      label={key}
+                      tooltip={i18n.str`You must enter a value in JavaScript 
Object Notation (JSON).`}
+                      side={
+                        <button class="button" onClick={(e) => {
+                          if (value.extra && value.extra[key] !== undefined) {
+                            console.log(value.extra)
+                            delete value.extra[key]
+                          }
+                          valueHandler({
+                            ...value,
+                          })
+                        }}>remove</button>
+                      }
+                    />
+                  })}
+                  <div class="field is-horizontal">
+                    <div class="field-label is-normal">
+                      <label class="label">
+                        <i18n.Translate>Custom field name</i18n.Translate>
+                        <span class="icon has-tooltip-right" 
data-tooltip={"new extra field"}>
+                          <i class="mdi mdi-information" />
+                        </span>
+                      </label>
+                    </div>
+                    <div class="field-body is-flex-grow-3">
+                      <div class="field">
+                        <p class="control">
+                          <input class="input " value={newField} onChange={(e) 
=> setNewField(e.currentTarget.value)} />
+                        </p>
+                      </div>
+                    </div>
+                    <button class="button" onClick={(e) => {
+                      setNewField("")
+                      valueHandler({
+                        ...value,
+                        extra: {
+                          ...(value.extra ?? {}),
+                          [newField]: ""
+                        }
+                      })
+                    }}>add</button>
+                  </div>
+                </InputGroup>
+              }
+            </FormProvider>
+
+            <div class="buttons is-right mt-5">
+              {onBack && (
+                <button class="button" onClick={onBack}>
+                  <i18n.Translate>Cancel</i18n.Translate>
+                </button>
+              )}
+              <button
+                class="button is-success"
+                onClick={submit}
+                disabled={hasErrors}
+              >
+                <i18n.Translate>Confirm</i18n.Translate>
+              </button>
+            </div>
+          </div>
+          <div class="column" />
+        </div>
+      </section>
+    </div>
+  );
+}
+
+function asProduct(p: ProductAndQuantity): MerchantBackend.Product {
+  return {
+    product_id: p.product.id,
+    image: p.product.image,
+    price: p.product.price,
+    unit: p.product.unit,
+    quantity: p.quantity,
+    description: p.product.description,
+    taxes: p.product.taxes,
+    minimum_age: p.product.minimum_age,
+  };
+}
+
+
+function DeadlineHelp({ duration }: { duration?: Duration }): VNode {
+  const { i18n } = useTranslationContext();
+  const [now, setNow] = useState(AbsoluteTime.now())
+  useEffect(() => {
+    const iid = setInterval(() => {
+      setNow(AbsoluteTime.now())
+    }, 60 * 1000)
+    return () => {
+      clearInterval(iid)
+    }
+  })
+  if (!duration) return <i18n.Translate>Disabled</i18n.Translate>
+  const when = AbsoluteTime.addDuration(now, duration)
+  if (when.t_ms === "never") return <i18n.Translate>No 
deadline</i18n.Translate>
+  return <i18n.Translate>Deadline at {format(when.t_ms, "dd/MM/yy 
HH:mm")}</i18n.Translate>
+}
diff --git 
a/packages/auditor-backoffice-ui/src/paths/instance/orders/create/OrderCreatedSuccessfully.tsx
 
b/packages/auditor-backoffice-ui/src/paths/instance/orders/create/OrderCreatedSuccessfully.tsx
new file mode 100644
index 000000000..88a984c97
--- /dev/null
+++ 
b/packages/auditor-backoffice-ui/src/paths/instance/orders/create/OrderCreatedSuccessfully.tsx
@@ -0,0 +1,114 @@
+/*
+ This file is part of GNU Taler
+ (C) 2021-2023 Taler Systems S.A.
+
+ GNU Taler is free software; you can redistribute it and/or modify it under the
+ terms of the GNU General Public License as published by the Free Software
+ Foundation; either version 3, or (at your option) any later version.
+
+ GNU Taler is distributed in the hope that it will be useful, but WITHOUT ANY
+ WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
+ A PARTICULAR PURPOSE.  See the GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License along with
+ GNU Taler; see the file COPYING.  If not, see <http://www.gnu.org/licenses/>
+ */
+import { useTranslationContext } from "@gnu-taler/web-util/browser";
+import { h, VNode } from "preact";
+import { useEffect, useState } from "preact/hooks";
+import { CreatedSuccessfully } from 
"../../../../components/notifications/CreatedSuccessfully.js";
+import { useOrderAPI } from "../../../../hooks/order.js";
+import { Entity } from "./index.js";
+
+interface Props {
+  entity: Entity;
+  onConfirm: () => void;
+  onCreateAnother?: () => void;
+}
+
+export function OrderCreatedSuccessfully({
+  entity,
+  onConfirm,
+  onCreateAnother,
+}: Props): VNode {
+  const { getPaymentURL } = useOrderAPI();
+  const [url, setURL] = useState<string | undefined>(undefined);
+  const { i18n } = useTranslationContext();
+  useEffect(() => {
+    getPaymentURL(entity.response.order_id).then((response) => {
+      setURL(response.data);
+    });
+  }, [getPaymentURL, entity.response.order_id]);
+
+  return (
+    <CreatedSuccessfully
+      onConfirm={onConfirm}
+      onCreateAnother={onCreateAnother}
+    >
+      <div class="field is-horizontal">
+        <div class="field-label is-normal">
+          <label class="label">
+            <i18n.Translate>Amount</i18n.Translate>
+          </label>
+        </div>
+        <div class="field-body is-flex-grow-3">
+          <div class="field">
+            <p class="control">
+              <input
+                class="input"
+                readonly
+                value={entity.request.order.amount}
+              />
+            </p>
+          </div>
+        </div>
+      </div>
+      <div class="field is-horizontal">
+        <div class="field-label is-normal">
+          <label class="label">
+            <i18n.Translate>Summary</i18n.Translate>
+          </label>
+        </div>
+        <div class="field-body is-flex-grow-3">
+          <div class="field">
+            <p class="control">
+              <input
+                class="input"
+                readonly
+                value={entity.request.order.summary}
+              />
+            </p>
+          </div>
+        </div>
+      </div>
+      <div class="field is-horizontal">
+        <div class="field-label is-normal">
+          <label class="label">
+            <i18n.Translate>Order ID</i18n.Translate>
+          </label>
+        </div>
+        <div class="field-body is-flex-grow-3">
+          <div class="field">
+            <p class="control">
+              <input class="input" readonly value={entity.response.order_id} />
+            </p>
+          </div>
+        </div>
+      </div>
+      <div class="field is-horizontal">
+        <div class="field-label is-normal">
+          <label class="label">
+            <i18n.Translate>Payment URL</i18n.Translate>
+          </label>
+        </div>
+        <div class="field-body is-flex-grow-3">
+          <div class="field">
+            <p class="control">
+              <input class="input" readonly value={url} />
+            </p>
+          </div>
+        </div>
+      </div>
+    </CreatedSuccessfully>
+  );
+}
diff --git 
a/packages/auditor-backoffice-ui/src/paths/instance/orders/create/index.tsx 
b/packages/auditor-backoffice-ui/src/paths/instance/orders/create/index.tsx
new file mode 100644
index 000000000..2474fd042
--- /dev/null
+++ b/packages/auditor-backoffice-ui/src/paths/instance/orders/create/index.tsx
@@ -0,0 +1,114 @@
+/*
+ This file is part of GNU Taler
+ (C) 2021-2023 Taler Systems S.A.
+
+ GNU Taler is free software; you can redistribute it and/or modify it under the
+ terms of the GNU General Public License as published by the Free Software
+ Foundation; either version 3, or (at your option) any later version.
+
+ GNU Taler is distributed in the hope that it will be useful, but WITHOUT ANY
+ WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
+ A PARTICULAR PURPOSE.  See the GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License along with
+ GNU Taler; see the file COPYING.  If not, see <http://www.gnu.org/licenses/>
+ */
+
+/**
+ *
+ * @author Sebastian Javier Marchano (sebasjm)
+ */
+
+import { ErrorType, HttpError } from "@gnu-taler/web-util/browser";
+import { Fragment, h, VNode } from "preact";
+import { useState } from "preact/hooks";
+import { Loading } from "../../../../components/exception/loading.js";
+import { NotificationCard } from "../../../../components/menu/index.js";
+import { MerchantBackend } from "../../../../declaration.js";
+import { useInstanceDetails } from "../../../../hooks/instance.js";
+import { useOrderAPI } from "../../../../hooks/order.js";
+import { useInstanceProducts } from "../../../../hooks/product.js";
+import { Notification } from "../../../../utils/types.js";
+import { CreatePage } from "./CreatePage.js";
+import { HttpStatusCode } from "@gnu-taler/taler-util";
+
+export type Entity = {
+  request: MerchantBackend.Orders.PostOrderRequest;
+  response: MerchantBackend.Orders.PostOrderResponse;
+};
+interface Props {
+  onBack?: () => void;
+  onConfirm: (id: string) => void;
+  onUnauthorized: () => VNode;
+  onNotFound: () => VNode;
+  onLoadError: (error: HttpError<MerchantBackend.ErrorDetail>) => VNode;
+}
+export default function OrderCreate({
+  onConfirm,
+  onBack,
+  onLoadError,
+  onNotFound,
+  onUnauthorized,
+}: Props): VNode {
+  const { createOrder } = useOrderAPI();
+  const [notif, setNotif] = useState<Notification | undefined>(undefined);
+
+  const detailsResult = useInstanceDetails();
+  const inventoryResult = useInstanceProducts();
+
+  if (detailsResult.loading) return <Loading />;
+  if (inventoryResult.loading) return <Loading />;
+
+  if (!detailsResult.ok) {
+    if (
+      detailsResult.type === ErrorType.CLIENT &&
+      detailsResult.status === HttpStatusCode.Unauthorized
+    )
+      return onUnauthorized();
+    if (
+      detailsResult.type === ErrorType.CLIENT &&
+      detailsResult.status === HttpStatusCode.NotFound
+    )
+      return onNotFound();
+    return onLoadError(detailsResult);
+  }
+
+  if (!inventoryResult.ok) {
+    if (
+      inventoryResult.type === ErrorType.CLIENT &&
+      inventoryResult.status === HttpStatusCode.Unauthorized
+    )
+      return onUnauthorized();
+    if (
+      inventoryResult.type === ErrorType.CLIENT &&
+      inventoryResult.status === HttpStatusCode.NotFound
+    )
+      return onNotFound();
+    return onLoadError(inventoryResult);
+  }
+
+  return (
+    <Fragment>
+      <NotificationCard notification={notif} />
+
+      <CreatePage
+        onBack={onBack}
+        onCreate={(request: MerchantBackend.Orders.PostOrderRequest) => {
+          createOrder(request)
+            .then((r) => {
+              return onConfirm(r.data.order_id)
+            })
+            .catch((error) => {
+              setNotif({
+                message: "could not create order",
+                type: "ERROR",
+                description: error.message,
+              });
+            });
+        }}
+        instanceConfig={detailsResult.data}
+        instanceInventory={inventoryResult.data}
+      />
+    </Fragment>
+  );
+}
diff --git 
a/packages/auditor-backoffice-ui/src/paths/instance/orders/details/Detail.stories.tsx
 
b/packages/auditor-backoffice-ui/src/paths/instance/orders/details/Detail.stories.tsx
new file mode 100644
index 000000000..6e73a01a5
--- /dev/null
+++ 
b/packages/auditor-backoffice-ui/src/paths/instance/orders/details/Detail.stories.tsx
@@ -0,0 +1,135 @@
+/*
+ This file is part of GNU Taler
+ (C) 2021-2023 Taler Systems S.A.
+
+ GNU Taler is free software; you can redistribute it and/or modify it under the
+ terms of the GNU General Public License as published by the Free Software
+ Foundation; either version 3, or (at your option) any later version.
+
+ GNU Taler is distributed in the hope that it will be useful, but WITHOUT ANY
+ WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
+ A PARTICULAR PURPOSE.  See the GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License along with
+ GNU Taler; see the file COPYING.  If not, see <http://www.gnu.org/licenses/>
+ */
+
+/**
+ *
+ * @author Sebastian Javier Marchano (sebasjm)
+ */
+
+import { addDays } from "date-fns";
+import { h, VNode, FunctionalComponent } from "preact";
+import { MerchantBackend } from "../../../../declaration.js";
+import { DetailPage as TestedComponent } from "./DetailPage.js";
+
+export default {
+  title: "Pages/Order/Detail",
+  component: TestedComponent,
+  argTypes: {
+    onRefund: { action: "onRefund" },
+    onBack: { action: "onBack" },
+  },
+};
+
+function createExample<Props>(
+  Component: FunctionalComponent<Props>,
+  props: Partial<Props>,
+) {
+  const r = (args: any) => <Component {...args} />;
+  r.args = props;
+  return r;
+}
+
+const defaultContractTerm = {
+  amount: "TESTKUDOS:10",
+  timestamp: {
+    t_s: new Date().getTime() / 1000,
+  },
+  auditors: [],
+  exchanges: [],
+  max_fee: "TESTKUDOS:1",
+  merchant: {} as any,
+  merchant_base_url: "http://merchant.url/";,
+  order_id: "2021.165-03GDFC26Y1NNG",
+  products: [],
+  summary: "text summary",
+  wire_transfer_deadline: {
+    t_s: "never",
+  },
+  refund_deadline: { t_s: "never" },
+  merchant_pub: "ASDASDASDSd",
+  nonce: "QWEQWEQWE",
+  pay_deadline: {
+    t_s: "never",
+  },
+  wire_method: "x-taler-bank",
+  h_wire: "asd",
+} as MerchantBackend.ContractTerms;
+
+// contract_terms: defaultContracTerm,
+export const Claimed = createExample(TestedComponent, {
+  id: "2021.165-03GDFC26Y1NNG",
+  selected: {
+    order_status: "claimed",
+    contract_terms: defaultContractTerm,
+  },
+});
+
+export const PaidNotRefundable = createExample(TestedComponent, {
+  id: "2021.165-03GDFC26Y1NNG",
+  selected: {
+    order_status: "paid",
+    contract_terms: defaultContractTerm,
+    refunded: false,
+    deposit_total: "TESTKUDOS:10",
+    exchange_ec: 0,
+    order_status_url: "http://merchant.backend/status";,
+    exchange_hc: 0,
+    refund_amount: "TESTKUDOS:0",
+    refund_details: [],
+    refund_pending: false,
+    wire_details: [],
+    wire_reports: [],
+    wired: false,
+  },
+});
+
+export const PaidRefundable = createExample(TestedComponent, {
+  id: "2021.165-03GDFC26Y1NNG",
+  selected: {
+    order_status: "paid",
+    contract_terms: {
+      ...defaultContractTerm,
+      refund_deadline: {
+        t_s: addDays(new Date(), 2).getTime() / 1000,
+      },
+    },
+    refunded: false,
+    deposit_total: "TESTKUDOS:10",
+    exchange_ec: 0,
+    order_status_url: "http://merchant.backend/status";,
+    exchange_hc: 0,
+    refund_amount: "TESTKUDOS:0",
+    refund_details: [],
+    refund_pending: false,
+    wire_details: [],
+    wire_reports: [],
+    wired: false,
+  },
+});
+
+export const Unpaid = createExample(TestedComponent, {
+  id: "2021.165-03GDFC26Y1NNG",
+  selected: {
+    order_status: "unpaid",
+    order_status_url: "http://merchant.backend/status";,
+    creation_time: {
+      t_s: new Date().getTime() / 1000,
+    },
+    summary: "text summary",
+    taler_pay_uri: "pay uri",
+    total_amount: "TESTKUDOS:10",
+  },
+});
diff --git 
a/packages/auditor-backoffice-ui/src/paths/instance/orders/details/DetailPage.tsx
 
b/packages/auditor-backoffice-ui/src/paths/instance/orders/details/DetailPage.tsx
new file mode 100644
index 000000000..5ff76e37a
--- /dev/null
+++ 
b/packages/auditor-backoffice-ui/src/paths/instance/orders/details/DetailPage.tsx
@@ -0,0 +1,770 @@
+/*
+ This file is part of GNU Taler
+ (C) 2021-2023 Taler Systems S.A.
+
+ GNU Taler is free software; you can redistribute it and/or modify it under the
+ terms of the GNU General Public License as published by the Free Software
+ Foundation; either version 3, or (at your option) any later version.
+
+ GNU Taler is distributed in the hope that it will be useful, but WITHOUT ANY
+ WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
+ A PARTICULAR PURPOSE.  See the GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License along with
+ GNU Taler; see the file COPYING.  If not, see <http://www.gnu.org/licenses/>
+ */
+
+/**
+ *
+ * @author Sebastian Javier Marchano (sebasjm)
+ */
+
+import { AmountJson, Amounts, stringifyRefundUri } from 
"@gnu-taler/taler-util";
+import { useTranslationContext } from "@gnu-taler/web-util/browser";
+import { format, formatDistance } from "date-fns";
+import { Fragment, VNode, h } from "preact";
+import { useState } from "preact/hooks";
+import { FormProvider } from "../../../../components/form/FormProvider.js";
+import { Input } from "../../../../components/form/Input.js";
+import { InputCurrency } from "../../../../components/form/InputCurrency.js";
+import { InputDate } from "../../../../components/form/InputDate.js";
+import { InputDuration } from "../../../../components/form/InputDuration.js";
+import { InputGroup } from "../../../../components/form/InputGroup.js";
+import { InputLocation } from "../../../../components/form/InputLocation.js";
+import { TextField } from "../../../../components/form/TextField.js";
+import { ProductList } from "../../../../components/product/ProductList.js";
+import { useBackendContext } from "../../../../context/backend.js";
+import { MerchantBackend } from "../../../../declaration.js";
+import { datetimeFormatForSettings, useSettings } from 
"../../../../hooks/useSettings.js";
+import { mergeRefunds } from "../../../../utils/amount.js";
+import { RefundModal } from "../list/Table.js";
+import { Event, Timeline } from "./Timeline.js";
+
+type Entity = MerchantBackend.Orders.MerchantOrderStatusResponse;
+type CT = MerchantBackend.ContractTerms;
+
+interface Props {
+  onBack: () => void;
+  selected: Entity;
+  id: string;
+  onRefund: (id: string, value: MerchantBackend.Orders.RefundRequest) => void;
+}
+
+type Paid = MerchantBackend.Orders.CheckPaymentPaidResponse & {
+  refund_taken: string;
+};
+type Unpaid = MerchantBackend.Orders.CheckPaymentUnpaidResponse;
+type Claimed = MerchantBackend.Orders.CheckPaymentClaimedResponse;
+
+function ContractTerms({ value }: { value: CT }) {
+  const { i18n } = useTranslationContext();
+
+  return (
+    <InputGroup name="contract_terms" label={i18n.str`Contract Terms`}>
+      <FormProvider<CT> object={value} valueHandler={null}>
+        <Input<CT>
+          readonly
+          name="summary"
+          label={i18n.str`Summary`}
+          tooltip={i18n.str`human-readable description of the whole purchase`}
+        />
+        <InputCurrency<CT>
+          readonly
+          name="amount"
+          label={i18n.str`Amount`}
+          tooltip={i18n.str`total price for the transaction`}
+        />
+        {value.fulfillment_url && (
+          <Input<CT>
+            readonly
+            name="fulfillment_url"
+            label={i18n.str`Fulfillment URL`}
+            tooltip={i18n.str`URL for this purchase`}
+          />
+        )}
+        <Input<CT>
+          readonly
+          name="max_fee"
+          label={i18n.str`Max fee`}
+          tooltip={i18n.str`maximum total deposit fee accepted by the merchant 
for this contract`}
+        />
+        <InputDate<CT>
+          readonly
+          name="timestamp"
+          label={i18n.str`Created at`}
+          tooltip={i18n.str`time when this contract was generated`}
+        />
+        <InputDate<CT>
+          readonly
+          name="refund_deadline"
+          label={i18n.str`Refund deadline`}
+          tooltip={i18n.str`after this deadline has passed no refunds will be 
accepted`}
+        />
+        <InputDate<CT>
+          readonly
+          name="pay_deadline"
+          label={i18n.str`Payment deadline`}
+          tooltip={i18n.str`after this deadline, the merchant won't accept 
payments for the contract`}
+        />
+        <InputDate<CT>
+          readonly
+          name="wire_transfer_deadline"
+          label={i18n.str`Wire transfer deadline`}
+          tooltip={i18n.str`transfer deadline for the exchange`}
+        />
+        <InputDate<CT>
+          readonly
+          name="delivery_date"
+          label={i18n.str`Delivery date`}
+          tooltip={i18n.str`time indicating when the order should be 
delivered`}
+        />
+        {value.delivery_date && (
+          <InputGroup
+            name="delivery_location"
+            label={i18n.str`Location`}
+            tooltip={i18n.str`where the order will be delivered`}
+          >
+            <InputLocation name="payments.delivery_location" />
+          </InputGroup>
+        )}
+        <InputDuration<CT>
+          readonly
+          name="auto_refund"
+          label={i18n.str`Auto-refund delay`}
+          tooltip={i18n.str`how long the wallet should try to get an automatic 
refund for the purchase`}
+        />
+        <Input<CT>
+          readonly
+          name="extra"
+          label={i18n.str`Extra info`}
+          tooltip={i18n.str`extra data that is only interpreted by the 
merchant frontend`}
+        />
+      </FormProvider>
+    </InputGroup>
+  );
+}
+
+function ClaimedPage({
+  id,
+  order,
+}: {
+  id: string;
+  order: MerchantBackend.Orders.CheckPaymentClaimedResponse;
+}) {
+  const events: Event[] = [];
+  if (order.contract_terms.timestamp.t_s !== "never") {
+    events.push({
+      when: new Date(order.contract_terms.timestamp.t_s * 1000),
+      description: "order created",
+      type: "start",
+    });
+  }
+  if (order.contract_terms.pay_deadline.t_s !== "never") {
+    events.push({
+      when: new Date(order.contract_terms.pay_deadline.t_s * 1000),
+      description: "pay deadline",
+      type: "deadline",
+    });
+  }
+  if (order.contract_terms.refund_deadline.t_s !== "never") {
+    events.push({
+      when: new Date(order.contract_terms.refund_deadline.t_s * 1000),
+      description: "refund deadline",
+      type: "deadline",
+    });
+  }
+  if (order.contract_terms.wire_transfer_deadline.t_s !== "never") {
+    events.push({
+      when: new Date(order.contract_terms.wire_transfer_deadline.t_s * 1000),
+      description: "wire deadline",
+      type: "deadline",
+    });
+  }
+  if (
+    order.contract_terms.delivery_date &&
+    order.contract_terms.delivery_date.t_s !== "never"
+  ) {
+    events.push({
+      when: new Date(order.contract_terms.delivery_date?.t_s * 1000),
+      description: "delivery",
+      type: "delivery",
+    });
+  }
+
+  const [value, valueHandler] = useState<Partial<Claimed>>(order);
+  const { i18n } = useTranslationContext();
+  const [settings] = useSettings()
+
+  return (
+    <div>
+      <section class="section">
+        <div class="columns">
+          <div class="column" />
+          <div class="column is-10">
+            <section class="hero is-hero-bar">
+              <div class="hero-body">
+                <div class="level">
+                  <div class="level-left">
+                    <div class="level-item">
+                      <i18n.Translate>Order</i18n.Translate> #{id}
+                      <div class="tag is-info ml-4">
+                        <i18n.Translate>claimed</i18n.Translate>
+                      </div>
+                    </div>
+                  </div>
+                </div>
+
+                <div class="level">
+                  <div class="level-left">
+                    <div class="level-item">
+                      <h1 class="title">{order.contract_terms.amount}</h1>
+                    </div>
+                  </div>
+                </div>
+
+                <div class="level">
+                  <div class="level-left" style={{ maxWidth: "100%" }}>
+                    <div class="level-item" style={{ maxWidth: "100%" }}>
+                      <div
+                        class="content"
+                        style={{
+                          whiteSpace: "nowrap",
+                          overflow: "hidden",
+                          textOverflow: "ellipsis",
+                        }}
+                      >
+                        <p>
+                          <b>
+                            <i18n.Translate>claimed at</i18n.Translate>:
+                          </b>{" "}
+                          {format(
+                            new Date(order.contract_terms.timestamp.t_s * 
1000),
+                            datetimeFormatForSettings(settings)
+                          )}
+                        </p>
+                      </div>
+                    </div>
+                  </div>
+                </div>
+              </div>
+            </section>
+
+            <section class="section">
+              <div class="columns">
+                <div class="column is-4">
+                  <div class="title">
+                    <i18n.Translate>Timeline</i18n.Translate>
+                  </div>
+                  <Timeline events={events} />
+                </div>
+                <div class="column is-8">
+                  <div class="title">
+                    <i18n.Translate>Payment details</i18n.Translate>
+                  </div>
+                  <FormProvider<Claimed>
+                    object={value}
+                    valueHandler={valueHandler}
+                  >
+                    <Input
+                      name="contract_terms.summary"
+                      readonly
+                      inputType="multiline"
+                      label={i18n.str`Summary`}
+                    />
+                    <InputCurrency
+                      name="contract_terms.amount"
+                      readonly
+                      label={i18n.str`Amount`}
+                    />
+                    <Input<Claimed>
+                      name="order_status"
+                      readonly
+                      label={i18n.str`Order status`}
+                    />
+                  </FormProvider>
+                </div>
+              </div>
+            </section>
+
+            {order.contract_terms.products.length ? (
+              <Fragment>
+                <div class="title">
+                  <i18n.Translate>Product list</i18n.Translate>
+                </div>
+                <ProductList list={order.contract_terms.products} />
+              </Fragment>
+            ) : undefined}
+
+            {value.contract_terms && (
+              <ContractTerms value={value.contract_terms} />
+            )}
+          </div>
+          <div class="column" />
+        </div>
+      </section>
+    </div>
+  );
+}
+function PaidPage({
+  id,
+  order,
+  onRefund,
+}: {
+  id: string;
+  order: MerchantBackend.Orders.CheckPaymentPaidResponse;
+  onRefund: (id: string) => void;
+}) {
+  const events: Event[] = [];
+  if (order.contract_terms.timestamp.t_s !== "never") {
+    events.push({
+      when: new Date(order.contract_terms.timestamp.t_s * 1000),
+      description: "order created",
+      type: "start",
+    });
+  }
+  if (order.contract_terms.pay_deadline.t_s !== "never") {
+    events.push({
+      when: new Date(order.contract_terms.pay_deadline.t_s * 1000),
+      description: "pay deadline",
+      type: "deadline",
+    });
+  }
+  if (order.contract_terms.refund_deadline.t_s !== "never") {
+    events.push({
+      when: new Date(order.contract_terms.refund_deadline.t_s * 1000),
+      description: "refund deadline",
+      type: "deadline",
+    });
+  }
+  if (order.contract_terms.wire_transfer_deadline.t_s !== "never") {
+    events.push({
+      when: new Date(order.contract_terms.wire_transfer_deadline.t_s * 1000),
+      description: "wire deadline",
+      type: "deadline",
+    });
+  }
+  if (
+    order.contract_terms.delivery_date &&
+    order.contract_terms.delivery_date.t_s !== "never"
+  ) {
+    if (order.contract_terms.delivery_date)
+      events.push({
+        when: new Date(order.contract_terms.delivery_date?.t_s * 1000),
+        description: "delivery",
+        type: "delivery",
+      });
+  }
+  order.refund_details.reduce(mergeRefunds, []).forEach((e) => {
+    if (e.timestamp.t_s !== "never") {
+      events.push({
+        when: new Date(e.timestamp.t_s * 1000),
+        description: `refund: ${e.amount}: ${e.reason}`,
+        type: e.pending ? "refund" : "refund-taken",
+      });
+    }
+  });
+  if (order.wire_details && order.wire_details.length) {
+    if (order.wire_details.length > 1) {
+      let last: MerchantBackend.Orders.TransactionWireTransfer | null = null;
+      let first: MerchantBackend.Orders.TransactionWireTransfer | null = null;
+      let total: AmountJson | null = null;
+
+      order.wire_details.forEach((w) => {
+        if (last === null || last.execution_time.t_s < w.execution_time.t_s) {
+          last = w;
+        }
+        if (first === null || first.execution_time.t_s > w.execution_time.t_s) 
{
+          first = w;
+        }
+        total =
+          total === null
+            ? Amounts.parseOrThrow(w.amount)
+            : Amounts.add(total, Amounts.parseOrThrow(w.amount)).amount;
+      });
+      const last_time = last!.execution_time.t_s;
+      if (last_time !== "never") {
+        events.push({
+          when: new Date(last_time * 1000),
+          description: `wired ${Amounts.stringify(total!)}`,
+          type: "wired-range",
+        });
+      }
+      const first_time = first!.execution_time.t_s;
+      if (first_time !== "never") {
+        events.push({
+          when: new Date(first_time * 1000),
+          description: `wire transfer started...`,
+          type: "wired-range",
+        });
+      }
+    } else {
+      order.wire_details.forEach((e) => {
+        if (e.execution_time.t_s !== "never") {
+          events.push({
+            when: new Date(e.execution_time.t_s * 1000),
+            description: `wired ${e.amount}`,
+            type: "wired",
+          });
+        }
+      });
+    }
+  }
+
+  const now = new Date()
+  const nextEvent = events.find((e) => {
+    return e.when.getTime() > now.getTime()
+  })
+
+  const [value, valueHandler] = useState<Partial<Paid>>(order);
+  const { url: backendURL } = useBackendContext()
+  const refundurl = stringifyRefundUri({
+    merchantBaseUrl: backendURL,
+    orderId: order.contract_terms.order_id
+  })
+  const refundable =
+    new Date().getTime() < order.contract_terms.refund_deadline.t_s * 1000;
+  const { i18n } = useTranslationContext();
+
+  const amount = Amounts.parseOrThrow(order.contract_terms.amount);
+  const refund_taken = order.refund_details.reduce((prev, cur) => {
+    if (cur.pending) return prev;
+    return Amounts.add(prev, Amounts.parseOrThrow(cur.amount)).amount;
+  }, Amounts.zeroOfCurrency(amount.currency));
+  value.refund_taken = Amounts.stringify(refund_taken);
+
+  return (
+    <div>
+      <section class="section">
+        <div class="columns">
+          <div class="column" />
+          <div class="column is-10">
+            <section class="hero is-hero-bar">
+              <div class="hero-body">
+                <div class="level">
+                  <div class="level-left">
+                    <div class="level-item">
+                      <i18n.Translate>Order</i18n.Translate> #{id}
+                      <div class="tag is-success ml-4">
+                        <i18n.Translate>paid</i18n.Translate>
+                      </div>
+                      {order.wired ? (
+                        <div class="tag is-success ml-4">
+                          <i18n.Translate>wired</i18n.Translate>
+                        </div>
+                      ) : null}
+                      {order.refunded ? (
+                        <div class="tag is-danger ml-4">
+                          <i18n.Translate>refunded</i18n.Translate>
+                        </div>
+                      ) : null}
+                    </div>
+                  </div>
+                </div>
+                <div class="level">
+                  <div class="level-left">
+                    <div class="level-item">
+                      <h1 class="title">{order.contract_terms.amount}</h1>
+                    </div>
+                  </div>
+                  <div class="level-right">
+                    <div class="level-item">
+                      <h1 class="title">
+                        <div class="buttons">
+                          <span
+                            class="has-tooltip-left"
+                            data-tooltip={
+                              refundable
+                                ? i18n.str`refund order`
+                                : i18n.str`not refundable`
+                            }
+                          >
+                            <button
+                              class="button is-danger"
+                              disabled={!refundable}
+                              onClick={() => onRefund(id)}
+                            >
+                              <i18n.Translate>refund</i18n.Translate>
+                            </button>
+                          </span>
+                        </div>
+                      </h1>
+                    </div>
+                  </div>
+                </div>
+
+                <div class="level">
+                  <div class="level-left" style={{ maxWidth: "100%" }}>
+                    <div class="level-item" style={{ maxWidth: "100%" }}>
+                      <div
+                        class="content"
+                        style={{
+                          whiteSpace: "nowrap",
+                          overflow: "hidden",
+                          textOverflow: "ellipsis",
+                        }}
+                      >
+                        {nextEvent &&
+                          <p>
+                            <i18n.Translate>Next event in </i18n.Translate> 
{formatDistance(
+                              nextEvent.when,
+                              new Date(),
+                              // "yyyy/MM/dd HH:mm:ss",
+                            )}
+                          </p>
+                        }
+                      </div>
+                    </div>
+                  </div>
+                </div>
+              </div>
+            </section>
+
+            <section class="section">
+              <div class="columns">
+                <div class="column is-4">
+                  <div class="title">
+                    <i18n.Translate>Timeline</i18n.Translate>
+                  </div>
+                  <Timeline events={events} />
+                </div>
+                <div class="column is-8">
+                  <div class="title">
+                    <i18n.Translate>Payment details</i18n.Translate>
+                  </div>
+                  <FormProvider<Paid>
+                    object={value}
+                    valueHandler={valueHandler}
+                  >
+                    {/* <InputCurrency<Paid> name="deposit_total" readonly 
label={i18n.str`Deposit total`} /> */}
+                    {order.refunded && (
+                      <InputCurrency<Paid>
+                        name="refund_amount"
+                        readonly
+                        label={i18n.str`Refunded amount`}
+                      />
+                    )}
+                    {order.refunded && (
+                      <InputCurrency<Paid>
+                        name="refund_taken"
+                        readonly
+                        label={i18n.str`Refund taken`}
+                      />
+                    )}
+                    <Input<Paid>
+                      name="order_status"
+                      readonly
+                      label={i18n.str`Order status`}
+                    />
+                    <TextField<Paid>
+                      name="order_status_url"
+                      label={i18n.str`Status URL`}
+                    >
+                      <a
+                        target="_blank"
+                        rel="noreferrer"
+                        href={order.order_status_url}
+                      >
+                        {order.order_status_url}
+                      </a>
+                    </TextField>
+                    {order.refunded && (
+                      <TextField<Paid>
+                        name="order_status_url"
+                        label={i18n.str`Refund URI`}
+                      >
+                        <a target="_blank" rel="noreferrer" href={refundurl}>
+                          {refundurl}
+                        </a>
+                      </TextField>
+                    )}
+                  </FormProvider>
+                </div>
+              </div>
+            </section>
+
+            {order.contract_terms.products.length ? (
+              <Fragment>
+                <div class="title">
+                  <i18n.Translate>Product list</i18n.Translate>
+                </div>
+                <ProductList list={order.contract_terms.products} />
+              </Fragment>
+            ) : undefined}
+
+            {value.contract_terms && (
+              <ContractTerms value={value.contract_terms} />
+            )}
+          </div>
+          <div class="column" />
+        </div>
+      </section>
+    </div>
+  );
+}
+
+function UnpaidPage({
+  id,
+  order,
+}: {
+  id: string;
+  order: MerchantBackend.Orders.CheckPaymentUnpaidResponse;
+}) {
+  const [value, valueHandler] = useState<Partial<Unpaid>>(order);
+  const { i18n } = useTranslationContext();
+  const [settings] = useSettings()
+  return (
+    <div>
+      <section class="hero is-hero-bar">
+        <div class="hero-body">
+          <div class="level">
+            <div class="level-left">
+              <div class="level-item">
+                <h1 class="title">
+                  <i18n.Translate>Order</i18n.Translate> #{id}
+                </h1>
+              </div>
+              <div class="tag is-dark">
+                <i18n.Translate>unpaid</i18n.Translate>
+              </div>
+            </div>
+          </div>
+
+          <div class="level">
+            <div class="level-left" style={{ maxWidth: "100%" }}>
+              <div class="level-item" style={{ maxWidth: "100%" }}>
+                <div
+                  class="content"
+                  style={{
+                    whiteSpace: "nowrap",
+                    overflow: "hidden",
+                    textOverflow: "ellipsis",
+                  }}
+                >
+                  <p>
+                    <b>
+                      <i18n.Translate>pay at</i18n.Translate>:
+                    </b>{" "}
+                    <a
+                      href={order.order_status_url}
+                      rel="nofollow"
+                      target="new"
+                    >
+                      {order.order_status_url}
+                    </a>
+                  </p>
+                  <p>
+                    <b>
+                      <i18n.Translate>created at</i18n.Translate>:
+                    </b>{" "}
+                    {order.creation_time.t_s === "never"
+                      ? "never"
+                      : format(
+                        new Date(order.creation_time.t_s * 1000),
+                        datetimeFormatForSettings(settings)
+                      )}
+                  </p>
+                </div>
+              </div>
+            </div>
+          </div>
+        </div>
+      </section>
+
+      <section class="section is-main-section">
+        <div class="columns">
+          <div class="column" />
+          <div class="column is-four-fifths">
+            <FormProvider<Unpaid> object={value} valueHandler={valueHandler}>
+              <Input<Unpaid>
+                readonly
+                name="summary"
+                label={i18n.str`Summary`}
+                tooltip={i18n.str`human-readable description of the whole 
purchase`}
+              />
+              <InputCurrency<Unpaid>
+                readonly
+                name="total_amount"
+                label={i18n.str`Amount`}
+                tooltip={i18n.str`total price for the transaction`}
+              />
+              <Input<Unpaid>
+                name="order_status"
+                readonly
+                label={i18n.str`Order status`}
+              />
+              <Input<Unpaid>
+                name="order_status_url"
+                readonly
+                label={i18n.str`Order status URL`}
+              />
+              <TextField<Unpaid>
+                name="taler_pay_uri"
+                label={i18n.str`Payment URI`}
+              >
+                <a target="_blank" rel="noreferrer" href={value.taler_pay_uri}>
+                  {value.taler_pay_uri}
+                </a>
+              </TextField>
+            </FormProvider>
+          </div>
+          <div class="column" />
+        </div>
+      </section>
+    </div>
+  );
+}
+
+export function DetailPage({ id, selected, onRefund, onBack }: Props): VNode {
+  const [showRefund, setShowRefund] = useState<string | undefined>(undefined);
+  const { i18n } = useTranslationContext();
+  const DetailByStatus = function () {
+    switch (selected.order_status) {
+      case "claimed":
+        return <ClaimedPage id={id} order={selected} />;
+      case "paid":
+        return <PaidPage id={id} order={selected} onRefund={setShowRefund} />;
+      case "unpaid":
+        return <UnpaidPage id={id} order={selected} />;
+      default:
+        return (
+          <div>
+            <i18n.Translate>
+              Unknown order status. This is an error, please contact the
+              administrator.
+            </i18n.Translate>
+          </div>
+        );
+    }
+  };
+
+  return (
+    <Fragment>
+      {DetailByStatus()}
+      {showRefund && (
+        <RefundModal
+          order={selected}
+          onCancel={() => setShowRefund(undefined)}
+          onConfirm={(value) => {
+            onRefund(showRefund, value);
+            setShowRefund(undefined);
+          }}
+        />
+      )}
+      <div class="columns">
+        <div class="column" />
+        <div class="column is-four-fifths">
+          <div class="buttons is-right mt-5">
+            <button class="button" onClick={onBack}>
+              <i18n.Translate>Back</i18n.Translate>
+            </button>
+          </div>
+        </div>
+        <div class="column" />
+      </div>
+    </Fragment>
+  );
+}
+
+async function copyToClipboard(text: string) {
+  return navigator.clipboard.writeText(text);
+}
diff --git 
a/packages/auditor-backoffice-ui/src/paths/instance/orders/details/Timeline.tsx 
b/packages/auditor-backoffice-ui/src/paths/instance/orders/details/Timeline.tsx
new file mode 100644
index 000000000..8c863f386
--- /dev/null
+++ 
b/packages/auditor-backoffice-ui/src/paths/instance/orders/details/Timeline.tsx
@@ -0,0 +1,129 @@
+/*
+ This file is part of GNU Taler
+ (C) 2021-2023 Taler Systems S.A.
+
+ GNU Taler is free software; you can redistribute it and/or modify it under the
+ terms of the GNU General Public License as published by the Free Software
+ Foundation; either version 3, or (at your option) any later version.
+
+ GNU Taler is distributed in the hope that it will be useful, but WITHOUT ANY
+ WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
+ A PARTICULAR PURPOSE.  See the GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License along with
+ GNU Taler; see the file COPYING.  If not, see <http://www.gnu.org/licenses/>
+ */
+import { format } from "date-fns";
+import { h } from "preact";
+import { useEffect, useState } from "preact/hooks";
+import { datetimeFormatForSettings, useSettings } from 
"../../../../hooks/useSettings.js";
+
+interface Props {
+  events: Event[];
+}
+
+export function Timeline({ events: e }: Props) {
+  const events = [...e];
+  events.push({
+    when: new Date(),
+    description: "now",
+    type: "now",
+  });
+
+  events.sort((a, b) => a.when.getTime() - b.when.getTime());
+  const [settings] = useSettings();
+  const [state, setState] = useState(events);
+  useEffect(() => {
+    const handle = setTimeout(() => {
+      const eventsWithoutNow = state.filter((e) => e.type !== "now");
+      eventsWithoutNow.push({
+        when: new Date(),
+        description: "now",
+        type: "now",
+      });
+      setState(eventsWithoutNow);
+    }, 1000);
+    return () => {
+      clearTimeout(handle);
+    };
+  });
+  return (
+    <div class="timeline">
+      {events.map((e, i) => {
+        return (
+          <div key={i} class="timeline-item">
+            {(() => {
+              switch (e.type) {
+                case "deadline":
+                  return (
+                    <div class="timeline-marker is-icon ">
+                      <i class="mdi mdi-flag" />
+                    </div>
+                  );
+                case "delivery":
+                  return (
+                    <div class="timeline-marker is-icon ">
+                      <i class="mdi mdi-delivery" />
+                    </div>
+                  );
+                case "start":
+                  return (
+                    <div class="timeline-marker is-icon">
+                      <i class="mdi mdi-flag " />
+                    </div>
+                  );
+                case "wired":
+                  return (
+                    <div class="timeline-marker is-icon is-success">
+                      <i class="mdi mdi-cash" />
+                    </div>
+                  );
+                case "wired-range":
+                  return (
+                    <div class="timeline-marker is-icon is-success">
+                      <i class="mdi mdi-cash" />
+                    </div>
+                  );
+                case "refund":
+                  return (
+                    <div class="timeline-marker is-icon is-danger">
+                      <i class="mdi mdi-cash" />
+                    </div>
+                  );
+                case "refund-taken":
+                  return (
+                    <div class="timeline-marker is-icon is-success">
+                      <i class="mdi mdi-cash" />
+                    </div>
+                  );
+                case "now":
+                  return (
+                    <div class="timeline-marker is-icon is-info">
+                      <i class="mdi mdi-clock" />
+                    </div>
+                  );
+              }
+            })()}
+            <div class="timeline-content">
+              {e.description !== "now" && <p class="heading">{format(e.when, 
datetimeFormatForSettings(settings))}</p>}
+              <p>{e.description}</p>
+            </div>
+          </div>
+        );
+      })}
+    </div>
+  );
+}
+export interface Event {
+  when: Date;
+  description: string;
+  type:
+  | "start"
+  | "refund"
+  | "refund-taken"
+  | "wired"
+  | "wired-range"
+  | "deadline"
+  | "delivery"
+  | "now";
+}
diff --git 
a/packages/auditor-backoffice-ui/src/paths/instance/orders/details/index.tsx 
b/packages/auditor-backoffice-ui/src/paths/instance/orders/details/index.tsx
new file mode 100644
index 000000000..1517a3c42
--- /dev/null
+++ b/packages/auditor-backoffice-ui/src/paths/instance/orders/details/index.tsx
@@ -0,0 +1,95 @@
+/*
+ This file is part of GNU Taler
+ (C) 2021-2023 Taler Systems S.A.
+
+ GNU Taler is free software; you can redistribute it and/or modify it under the
+ terms of the GNU General Public License as published by the Free Software
+ Foundation; either version 3, or (at your option) any later version.
+
+ GNU Taler is distributed in the hope that it will be useful, but WITHOUT ANY
+ WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
+ A PARTICULAR PURPOSE.  See the GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License along with
+ GNU Taler; see the file COPYING.  If not, see <http://www.gnu.org/licenses/>
+ */
+import {
+  useTranslationContext,
+  HttpError,
+  ErrorType,
+} from "@gnu-taler/web-util/browser";
+import { Fragment, h, VNode } from "preact";
+import { useState } from "preact/hooks";
+import { Loading } from "../../../../components/exception/loading.js";
+import { NotificationCard } from "../../../../components/menu/index.js";
+import { MerchantBackend } from "../../../../declaration.js";
+import { useOrderAPI, useOrderDetails } from "../../../../hooks/order.js";
+import { Notification } from "../../../../utils/types.js";
+import { DetailPage } from "./DetailPage.js";
+import { HttpStatusCode } from "@gnu-taler/taler-util";
+
+export interface Props {
+  oid: string;
+
+  onBack: () => void;
+  onUnauthorized: () => VNode;
+  onNotFound: () => VNode;
+  onLoadError: (error: HttpError<MerchantBackend.ErrorDetail>) => VNode;
+}
+
+export default function Update({
+  oid,
+  onBack,
+  onLoadError,
+  onNotFound,
+  onUnauthorized,
+}: Props): VNode {
+  const { refundOrder } = useOrderAPI();
+  const result = useOrderDetails(oid);
+  const [notif, setNotif] = useState<Notification | undefined>(undefined);
+
+  const { i18n } = useTranslationContext();
+
+  if (result.loading) return <Loading />;
+  if (!result.ok) {
+    if (
+      result.type === ErrorType.CLIENT &&
+      result.status === HttpStatusCode.Unauthorized
+    )
+      return onUnauthorized();
+    if (
+      result.type === ErrorType.CLIENT &&
+      result.status === HttpStatusCode.NotFound
+    )
+      return onNotFound();
+    return onLoadError(result);
+  }
+
+  return (
+    <Fragment>
+      <NotificationCard notification={notif} />
+
+      <DetailPage
+        onBack={onBack}
+        id={oid}
+        onRefund={(id, value) =>
+          refundOrder(id, value)
+            .then(() =>
+              setNotif({
+                message: i18n.str`refund created successfully`,
+                type: "SUCCESS",
+              }),
+            )
+            .catch((error) =>
+              setNotif({
+                message: i18n.str`could not create the refund`,
+                type: "ERROR",
+                description: error.message,
+              }),
+            )
+        }
+        selected={result.data}
+      />
+    </Fragment>
+  );
+}
diff --git 
a/packages/auditor-backoffice-ui/src/paths/instance/orders/list/List.stories.tsx
 
b/packages/auditor-backoffice-ui/src/paths/instance/orders/list/List.stories.tsx
new file mode 100644
index 000000000..156c577f4
--- /dev/null
+++ 
b/packages/auditor-backoffice-ui/src/paths/instance/orders/list/List.stories.tsx
@@ -0,0 +1,107 @@
+/*
+ This file is part of GNU Taler
+ (C) 2021-2023 Taler Systems S.A.
+
+ GNU Taler is free software; you can redistribute it and/or modify it under the
+ terms of the GNU General Public License as published by the Free Software
+ Foundation; either version 3, or (at your option) any later version.
+
+ GNU Taler is distributed in the hope that it will be useful, but WITHOUT ANY
+ WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
+ A PARTICULAR PURPOSE.  See the GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License along with
+ GNU Taler; see the file COPYING.  If not, see <http://www.gnu.org/licenses/>
+ */
+
+/**
+ *
+ * @author Sebastian Javier Marchano (sebasjm)
+ */
+
+import { h, VNode, FunctionalComponent } from "preact";
+import { ListPage as TestedComponent } from "./ListPage.js";
+
+export default {
+  title: "Pages/Order/List",
+  component: TestedComponent,
+  argTypes: {
+    onShowAll: { action: "onShowAll" },
+    onShowPaid: { action: "onShowPaid" },
+    onShowRefunded: { action: "onShowRefunded" },
+    onShowNotWired: { action: "onShowNotWired" },
+    onCopyURL: { action: "onCopyURL" },
+    onSelectDate: { action: "onSelectDate" },
+    onLoadMoreBefore: { action: "onLoadMoreBefore" },
+    onLoadMoreAfter: { action: "onLoadMoreAfter" },
+    onSelectOrder: { action: "onSelectOrder" },
+    onRefundOrder: { action: "onRefundOrder" },
+    onSearchOrderById: { action: "onSearchOrderById" },
+    onCreate: { action: "onCreate" },
+  },
+};
+
+function createExample<Props>(
+  Component: FunctionalComponent<Props>,
+  props: Partial<Props>,
+) {
+  const r = (args: any) => <Component {...args} />;
+  r.args = props;
+  return r;
+}
+
+export const Example = createExample(TestedComponent, {
+  orders: [
+    {
+      id: "123",
+      amount: "TESTKUDOS:10",
+      paid: false,
+      refundable: true,
+      row_id: 1,
+      summary: "summary",
+      timestamp: {
+        t_s: new Date().getTime() / 1000,
+      },
+      order_id: "123",
+    },
+    {
+      id: "234",
+      amount: "TESTKUDOS:12",
+      paid: true,
+      refundable: true,
+      row_id: 2,
+      summary:
+        "summary with long text, very very long text that someone want to add 
as a description of the order",
+      timestamp: {
+        t_s: new Date().getTime() / 1000,
+      },
+      order_id: "234",
+    },
+    {
+      id: "456",
+      amount: "TESTKUDOS:1",
+      paid: false,
+      refundable: false,
+      row_id: 3,
+      summary:
+        "summary with long text, very very long text that someone want to add 
as a description of the order",
+      timestamp: {
+        t_s: new Date().getTime() / 1000,
+      },
+      order_id: "456",
+    },
+    {
+      id: "234",
+      amount: "TESTKUDOS:12",
+      paid: false,
+      refundable: false,
+      row_id: 4,
+      summary:
+        "summary with long text, very very long text that someone want to add 
as a description of the order",
+      timestamp: {
+        t_s: new Date().getTime() / 1000,
+      },
+      order_id: "234",
+    },
+  ],
+});
diff --git 
a/packages/auditor-backoffice-ui/src/paths/instance/orders/list/ListPage.tsx 
b/packages/auditor-backoffice-ui/src/paths/instance/orders/list/ListPage.tsx
new file mode 100644
index 000000000..9f80719a1
--- /dev/null
+++ b/packages/auditor-backoffice-ui/src/paths/instance/orders/list/ListPage.tsx
@@ -0,0 +1,226 @@
+/*
+ This file is part of GNU Taler
+ (C) 2021-2023 Taler Systems S.A.
+
+ GNU Taler is free software; you can redistribute it and/or modify it under the
+ terms of the GNU General Public License as published by the Free Software
+ Foundation; either version 3, or (at your option) any later version.
+
+ GNU Taler is distributed in the hope that it will be useful, but WITHOUT ANY
+ WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
+ A PARTICULAR PURPOSE.  See the GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License along with
+ GNU Taler; see the file COPYING.  If not, see <http://www.gnu.org/licenses/>
+ */
+
+/**
+ *
+ * @author Sebastian Javier Marchano (sebasjm)
+ */
+
+import { useTranslationContext } from "@gnu-taler/web-util/browser";
+import { format } from "date-fns";
+import { h, VNode, Fragment } from "preact";
+import { useState } from "preact/hooks";
+import { DatePicker } from "../../../../components/picker/DatePicker.js";
+import { MerchantBackend, WithId } from "../../../../declaration.js";
+import { CardTable } from "./Table.js";
+import { dateFormatForSettings, useSettings } from 
"../../../../hooks/useSettings.js";
+
+export interface ListPageProps {
+  onShowAll: () => void;
+  onShowNotPaid: () => void;
+  onShowPaid: () => void;
+  onShowRefunded: () => void;
+  onShowNotWired: () => void;
+  onShowWired: () => void;
+  onCopyURL: (id: string) => void;
+  isAllActive: string;
+  isPaidActive: string;
+  isNotPaidActive: string;
+  isRefundedActive: string;
+  isNotWiredActive: string;
+  isWiredActive: string;
+
+  jumpToDate?: Date;
+  onSelectDate: (date?: Date) => void;
+
+  orders: (MerchantBackend.Orders.OrderHistoryEntry & WithId)[];
+  onLoadMoreBefore?: () => void;
+  hasMoreBefore?: boolean;
+  hasMoreAfter?: boolean;
+  onLoadMoreAfter?: () => void;
+
+  onSelectOrder: (o: MerchantBackend.Orders.OrderHistoryEntry & WithId) => 
void;
+  onRefundOrder: (o: MerchantBackend.Orders.OrderHistoryEntry & WithId) => 
void;
+  onCreate: () => void;
+}
+
+export function ListPage({
+  hasMoreAfter,
+  hasMoreBefore,
+  onLoadMoreAfter,
+  onLoadMoreBefore,
+  orders,
+  isAllActive,
+  onSelectOrder,
+  onRefundOrder,
+  jumpToDate,
+  onCopyURL,
+  onShowAll,
+  onShowPaid,
+  onShowNotPaid,
+  onShowRefunded,
+  onShowNotWired,
+  onShowWired,
+  onSelectDate,
+  isPaidActive,
+  isRefundedActive,
+  isNotWiredActive,
+  onCreate,
+  isNotPaidActive,
+  isWiredActive,
+}: ListPageProps): VNode {
+  const { i18n } = useTranslationContext();
+  const dateTooltip = i18n.str`select date to show nearby orders`;
+  const [pickDate, setPickDate] = useState(false);
+  const [settings] = useSettings();
+
+  return (
+    <Fragment>
+      <div class="columns">
+        <div class="column is-two-thirds">
+          <div class="tabs" style={{ overflow: "inherit" }}>
+            <ul>
+              <li class={isNotPaidActive}>
+                <div
+                  class="has-tooltip-right"
+                  data-tooltip={i18n.str`only show paid orders`}
+                >
+                  <a onClick={onShowNotPaid}>
+                    <i18n.Translate>New</i18n.Translate>
+                  </a>
+                </div>
+              </li>
+              <li class={isPaidActive}>
+                <div
+                  class="has-tooltip-right"
+                  data-tooltip={i18n.str`only show paid orders`}
+                >
+                  <a onClick={onShowPaid}>
+                    <i18n.Translate>Paid</i18n.Translate>
+                  </a>
+                </div>
+              </li>
+              <li class={isRefundedActive}>
+                <div
+                  class="has-tooltip-right"
+                  data-tooltip={i18n.str`only show orders with refunds`}
+                >
+                  <a onClick={onShowRefunded}>
+                    <i18n.Translate>Refunded</i18n.Translate>
+                  </a>
+                </div>
+              </li>
+              <li class={isNotWiredActive}>
+                <div
+                  class="has-tooltip-left"
+                  data-tooltip={i18n.str`only show orders where customers 
paid, but wire payments from payment provider are still pending`}
+                >
+                  <a onClick={onShowNotWired}>
+                    <i18n.Translate>Not wired</i18n.Translate>
+                  </a>
+                </div>
+              </li>
+              <li class={isWiredActive}>
+                <div
+                  class="has-tooltip-left"
+                  data-tooltip={i18n.str`only show orders where customers 
paid, but wire payments from payment provider are still pending`}
+                >
+                  <a onClick={onShowWired}>
+                    <i18n.Translate>Completed</i18n.Translate>
+                  </a>
+                </div>
+              </li>
+              <li class={isAllActive}>
+                <div
+                  class="has-tooltip-right"
+                  data-tooltip={i18n.str`remove all filters`}
+                >
+                  <a onClick={onShowAll}>
+                    <i18n.Translate>All</i18n.Translate>
+                  </a>
+                </div>
+              </li>
+            </ul>
+          </div>
+        </div>
+        <div class="column ">
+          <div class="buttons is-right">
+            <div class="field has-addons">
+              {jumpToDate && (
+                <div class="control">
+                  <a class="button is-fullwidth" onClick={() => 
onSelectDate(undefined)}>
+                    <span
+                      class="icon"
+                      data-tooltip={i18n.str`clear date filter`}
+                    >
+                      <i class="mdi mdi-close" />
+                    </span>
+                  </a>
+                </div>
+              )}
+              <div class="control">
+                <span class="has-tooltip-top" data-tooltip={dateTooltip}>
+                  <input
+                    class="input"
+                    type="text"
+                    readonly
+                    value={!jumpToDate ? "" : format(jumpToDate, 
dateFormatForSettings(settings))}
+                    placeholder={i18n.str`date 
(${dateFormatForSettings(settings)})`}
+                    onClick={() => {
+                      setPickDate(true);
+                    }}
+                  />
+                </span>
+              </div>
+              <div class="control">
+                <span class="has-tooltip-left" data-tooltip={dateTooltip}>
+                  <a
+                    class="button  is-fullwidth"
+                    onClick={() => {
+                      setPickDate(true);
+                    }}
+                  >
+                    <span class="icon">
+                      <i class="mdi mdi-calendar" />
+                    </span>
+                  </a>
+                </span>
+              </div>
+            </div>
+          </div>
+        </div>
+      </div>
+
+      <DatePicker
+        opened={pickDate}
+        closeFunction={() => setPickDate(false)}
+        dateReceiver={onSelectDate}
+      />
+
+      <CardTable
+        orders={orders}
+        onCreate={onCreate}
+        onCopyURL={onCopyURL}
+        onSelect={onSelectOrder}
+        onRefund={onRefundOrder}
+        hasMoreAfter={hasMoreAfter}
+        hasMoreBefore={hasMoreBefore}
+        onLoadMoreAfter={onLoadMoreAfter}
+        onLoadMoreBefore={onLoadMoreBefore}
+      />
+    </Fragment>
+  );
+}
diff --git 
a/packages/auditor-backoffice-ui/src/paths/instance/orders/list/Table.tsx 
b/packages/auditor-backoffice-ui/src/paths/instance/orders/list/Table.tsx
new file mode 100644
index 000000000..b2806bb79
--- /dev/null
+++ b/packages/auditor-backoffice-ui/src/paths/instance/orders/list/Table.tsx
@@ -0,0 +1,417 @@
+/*
+ This file is part of GNU Taler
+ (C) 2021-2023 Taler Systems S.A.
+
+ GNU Taler is free software; you can redistribute it and/or modify it under the
+ terms of the GNU General Public License as published by the Free Software
+ Foundation; either version 3, or (at your option) any later version.
+
+ GNU Taler is distributed in the hope that it will be useful, but WITHOUT ANY
+ WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
+ A PARTICULAR PURPOSE.  See the GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License along with
+ GNU Taler; see the file COPYING.  If not, see <http://www.gnu.org/licenses/>
+ */
+
+/**
+ *
+ * @author Sebastian Javier Marchano (sebasjm)
+ */
+
+import { Amounts } from "@gnu-taler/taler-util";
+import { useTranslationContext } from "@gnu-taler/web-util/browser";
+import { format } from "date-fns";
+import { h, VNode } from "preact";
+import { StateUpdater, useState } from "preact/hooks";
+import {
+  FormErrors,
+  FormProvider,
+} from "../../../../components/form/FormProvider.js";
+import { Input } from "../../../../components/form/Input.js";
+import { InputCurrency } from "../../../../components/form/InputCurrency.js";
+import { InputGroup } from "../../../../components/form/InputGroup.js";
+import { InputSelector } from "../../../../components/form/InputSelector.js";
+import { ConfirmModal } from "../../../../components/modal/index.js";
+import { useConfigContext } from "../../../../context/config.js";
+import { MerchantBackend, WithId } from "../../../../declaration.js";
+import { mergeRefunds } from "../../../../utils/amount.js";
+import { datetimeFormatForSettings, useSettings } from 
"../../../../hooks/useSettings.js";
+
+type Entity = MerchantBackend.Orders.OrderHistoryEntry & WithId;
+interface Props {
+  orders: Entity[];
+  onRefund: (value: Entity) => void;
+  onCopyURL: (id: string) => void;
+  onCreate: () => void;
+  onSelect: (order: Entity) => void;
+  onLoadMoreBefore?: () => void;
+  hasMoreBefore?: boolean;
+  hasMoreAfter?: boolean;
+  onLoadMoreAfter?: () => void;
+}
+
+export function CardTable({
+  orders,
+  onCreate,
+  onRefund,
+  onCopyURL,
+  onSelect,
+  onLoadMoreAfter,
+  onLoadMoreBefore,
+  hasMoreAfter,
+  hasMoreBefore,
+}: Props): VNode {
+  const [rowSelection, rowSelectionHandler] = useState<string[]>([]);
+
+  const { i18n } = useTranslationContext();
+
+  return (
+    <div class="card has-table">
+      <header class="card-header">
+        <p class="card-header-title">
+          <span class="icon">
+            <i class="mdi mdi-cash-register" />
+          </span>
+          <i18n.Translate>Orders</i18n.Translate>
+        </p>
+
+        <div class="card-header-icon" aria-label="more options" />
+
+        <div class="card-header-icon" aria-label="more options">
+          <span class="has-tooltip-left" data-tooltip={i18n.str`create order`}>
+            <button class="button is-info" type="button" onClick={onCreate}>
+              <span class="icon is-small">
+                <i class="mdi mdi-plus mdi-36px" />
+              </span>
+            </button>
+          </span>
+        </div>
+      </header>
+      <div class="card-content">
+        <div class="b-table has-pagination">
+          <div class="table-wrapper has-mobile-cards">
+            {orders.length > 0 ? (
+              <Table
+                instances={orders}
+                onSelect={onSelect}
+                onRefund={onRefund}
+                onCopyURL={(o) => onCopyURL(o.id)}
+                rowSelection={rowSelection}
+                rowSelectionHandler={rowSelectionHandler}
+                onLoadMoreAfter={onLoadMoreAfter}
+                onLoadMoreBefore={onLoadMoreBefore}
+                hasMoreAfter={hasMoreAfter}
+                hasMoreBefore={hasMoreBefore}
+              />
+            ) : (
+              <EmptyTable />
+            )}
+          </div>
+        </div>
+      </div>
+    </div>
+  );
+}
+interface TableProps {
+  rowSelection: string[];
+  instances: Entity[];
+  onRefund: (id: Entity) => void;
+  onCopyURL: (id: Entity) => void;
+  onSelect: (id: Entity) => void;
+  rowSelectionHandler: StateUpdater<string[]>;
+  onLoadMoreBefore?: () => void;
+  hasMoreBefore?: boolean;
+  hasMoreAfter?: boolean;
+  onLoadMoreAfter?: () => void;
+}
+
+function Table({
+  instances,
+  onSelect,
+  onRefund,
+  onCopyURL,
+  onLoadMoreAfter,
+  onLoadMoreBefore,
+  hasMoreAfter,
+  hasMoreBefore,
+}: TableProps): VNode {
+  const { i18n } = useTranslationContext();
+  const [settings] = useSettings();
+  return (
+    <div class="table-container">
+      {hasMoreBefore && (
+        <button
+          class="button is-fullwidth"
+          onClick={onLoadMoreBefore}
+        >
+          <i18n.Translate>load newer orders</i18n.Translate>
+        </button>
+      )}
+      <table class="table is-striped is-hoverable is-fullwidth">
+        <thead>
+          <tr>
+            <th style={{ minWidth: 100 }}>
+              <i18n.Translate>Date</i18n.Translate>
+            </th>
+            <th style={{ minWidth: 100 }}>
+              <i18n.Translate>Amount</i18n.Translate>
+            </th>
+            <th style={{ minWidth: 400 }}>
+              <i18n.Translate>Summary</i18n.Translate>
+            </th>
+            <th style={{ minWidth: 50 }} />
+          </tr>
+        </thead>
+        <tbody>
+          {instances.map((i) => {
+            return (
+              <tr key={i.id}>
+                <td
+                  onClick={(): void => onSelect(i)}
+                  style={{ cursor: "pointer" }}
+                >
+                  {i.timestamp.t_s === "never"
+                    ? "never"
+                    : format(
+                      new Date(i.timestamp.t_s * 1000),
+                      datetimeFormatForSettings(settings),
+                    )}
+                </td>
+                <td
+                  onClick={(): void => onSelect(i)}
+                  style={{ cursor: "pointer" }}
+                >
+                  {i.amount}
+                </td>
+                <td
+                  onClick={(): void => onSelect(i)}
+                  style={{ cursor: "pointer" }}
+                >
+                  {i.summary}
+                </td>
+                <td class="is-actions-cell right-sticky">
+                  <div class="buttons is-right">
+                    {i.refundable && (
+                      <button
+                        class="button is-small is-danger jb-modal"
+                        type="button"
+                        onClick={(): void => onRefund(i)}
+                      >
+                        <i18n.Translate>Refund</i18n.Translate>
+                      </button>
+                    )}
+                    {!i.paid && (
+                      <button
+                        class="button is-small is-info jb-modal"
+                        type="button"
+                        onClick={(): void => onCopyURL(i)}
+                      >
+                        <i18n.Translate>copy url</i18n.Translate>
+                      </button>
+                    )}
+                  </div>
+                </td>
+              </tr>
+            );
+          })}
+        </tbody>
+      </table>
+      {hasMoreAfter && (
+        <button
+          class="button is-fullwidth"
+          onClick={onLoadMoreAfter}
+        >
+          <i18n.Translate>load older orders</i18n.Translate>
+        </button>
+      )}
+    </div>
+  );
+}
+
+function EmptyTable(): VNode {
+  const { i18n } = useTranslationContext();
+  return (
+    <div class="content has-text-grey has-text-centered">
+      <p>
+        <span class="icon is-large">
+          <i class="mdi mdi-emoticon-sad mdi-48px" />
+        </span>
+      </p>
+      <p>
+        <i18n.Translate>
+          No orders have been found matching your query!
+        </i18n.Translate>
+      </p>
+    </div>
+  );
+}
+
+interface RefundModalProps {
+  onCancel: () => void;
+  onConfirm: (value: MerchantBackend.Orders.RefundRequest) => void;
+  order: MerchantBackend.Orders.MerchantOrderStatusResponse;
+}
+
+export function RefundModal({
+  order,
+  onCancel,
+  onConfirm,
+}: RefundModalProps): VNode {
+  type State = { mainReason?: string; description?: string; refund?: string };
+  const [form, setValue] = useState<State>({});
+  const [settings] = useSettings();
+  const { i18n } = useTranslationContext();
+  // const [errors, setErrors] = useState<FormErrors<State>>({});
+
+  const refunds = (
+    order.order_status === "paid" ? order.refund_details : []
+  ).reduce(mergeRefunds, []);
+
+  const config = useConfigContext();
+  const totalRefunded = refunds
+    .map((r) => r.amount)
+    .reduce(
+      (p, c) => Amounts.add(p, Amounts.parseOrThrow(c)).amount,
+      Amounts.zeroOfCurrency(config.currency),
+    );
+  const orderPrice =
+    order.order_status === "paid"
+      ? Amounts.parseOrThrow(order.contract_terms.amount)
+      : undefined;
+  const totalRefundable = !orderPrice
+    ? Amounts.zeroOfCurrency(totalRefunded.currency)
+    : refunds.length
+      ? Amounts.sub(orderPrice, totalRefunded).amount
+      : orderPrice;
+
+  const isRefundable = Amounts.isNonZero(totalRefundable);
+  const duplicatedText = i18n.str`duplicated`;
+
+  const errors: FormErrors<State> = {
+    mainReason: !form.mainReason ? i18n.str`required` : undefined,
+    description:
+      !form.description && form.mainReason !== duplicatedText
+        ? i18n.str`required`
+        : undefined,
+    refund: !form.refund
+      ? i18n.str`required`
+      : !Amounts.parse(form.refund)
+        ? i18n.str`invalid format`
+        : Amounts.cmp(totalRefundable, Amounts.parse(form.refund)!) === -1
+          ? i18n.str`this value exceed the refundable amount`
+          : undefined,
+  };
+  const hasErrors = Object.keys(errors).some(
+    (k) => (errors as any)[k] !== undefined,
+  );
+
+  const validateAndConfirm = () => {
+    try {
+      if (!form.refund) return;
+      onConfirm({
+        refund: Amounts.stringify(
+          Amounts.add(Amounts.parse(form.refund)!, totalRefunded).amount,
+        ),
+        reason:
+          form.description === undefined
+            ? form.mainReason || ""
+            : `${form.mainReason}: ${form.description}`,
+      });
+    } catch (err) {
+      console.log(err);
+    }
+  };
+
+  //FIXME: parameters in the translation
+  return (
+    <ConfirmModal
+      description="refund"
+      danger
+      active
+      disabled={!isRefundable || hasErrors}
+      onCancel={onCancel}
+      onConfirm={validateAndConfirm}
+    >
+      {refunds.length > 0 && (
+        <div class="columns">
+          <div class="column is-12">
+            <InputGroup
+              name="asd"
+              label={`${Amounts.stringify(totalRefunded)} was already 
refunded`}
+            >
+              <table class="table is-fullwidth">
+                <thead>
+                  <tr>
+                    <th>
+                      <i18n.Translate>date</i18n.Translate>
+                    </th>
+                    <th>
+                      <i18n.Translate>amount</i18n.Translate>
+                    </th>
+                    <th>
+                      <i18n.Translate>reason</i18n.Translate>
+                    </th>
+                  </tr>
+                </thead>
+                <tbody>
+                  {refunds.map((r) => {
+                    return (
+                      <tr key={r.timestamp.t_s}>
+                        <td>
+                          {r.timestamp.t_s === "never"
+                            ? "never"
+                            : format(
+                              new Date(r.timestamp.t_s * 1000),
+                              datetimeFormatForSettings(settings),
+                            )}
+                        </td>
+                        <td>{r.amount}</td>
+                        <td>{r.reason}</td>
+                      </tr>
+                    );
+                  })}
+                </tbody>
+              </table>
+            </InputGroup>
+          </div>
+        </div>
+      )}
+
+      {isRefundable && (
+        <FormProvider<State>
+          errors={errors}
+          object={form}
+          valueHandler={(d) => setValue(d as any)}
+        >
+          <InputCurrency<State>
+            name="refund"
+            label={i18n.str`Refund`}
+            tooltip={i18n.str`amount to be refunded`}
+          >
+            <i18n.Translate>Max refundable:</i18n.Translate>{" "}
+            {Amounts.stringify(totalRefundable)}
+          </InputCurrency>
+          <InputSelector
+            name="mainReason"
+            label={i18n.str`Reason`}
+            values={[
+              i18n.str`Choose one...`,
+              duplicatedText,
+              i18n.str`requested by the customer`,
+              i18n.str`other`,
+            ]}
+            tooltip={i18n.str`why this order is being refunded`}
+          />
+          {form.mainReason && form.mainReason !== duplicatedText ? (
+            <Input<State>
+              label={i18n.str`Description`}
+              name="description"
+              tooltip={i18n.str`more information to give context`}
+            />
+          ) : undefined}
+        </FormProvider>
+      )}
+    </ConfirmModal>
+  );
+}
diff --git 
a/packages/auditor-backoffice-ui/src/paths/instance/orders/list/index.tsx 
b/packages/auditor-backoffice-ui/src/paths/instance/orders/list/index.tsx
new file mode 100644
index 000000000..34c7d348a
--- /dev/null
+++ b/packages/auditor-backoffice-ui/src/paths/instance/orders/list/index.tsx
@@ -0,0 +1,231 @@
+/*
+ This file is part of GNU Taler
+ (C) 2021-2023 Taler Systems S.A.
+
+ GNU Taler is free software; you can redistribute it and/or modify it under the
+ terms of the GNU General Public License as published by the Free Software
+ Foundation; either version 3, or (at your option) any later version.
+
+ GNU Taler is distributed in the hope that it will be useful, but WITHOUT ANY
+ WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
+ A PARTICULAR PURPOSE.  See the GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License along with
+ GNU Taler; see the file COPYING.  If not, see <http://www.gnu.org/licenses/>
+ */
+
+/**
+ *
+ * @author Sebastian Javier Marchano (sebasjm)
+ */
+
+import {
+  ErrorType,
+  HttpError,
+  useTranslationContext,
+} from "@gnu-taler/web-util/browser";
+import { Fragment, h, VNode } from "preact";
+import { useState } from "preact/hooks";
+import { Loading } from "../../../../components/exception/loading.js";
+import { NotificationCard } from "../../../../components/menu/index.js";
+import { MerchantBackend } from "../../../../declaration.js";
+import {
+  InstanceOrderFilter,
+  useInstanceOrders,
+  useOrderAPI,
+  useOrderDetails,
+} from "../../../../hooks/order.js";
+import { Notification } from "../../../../utils/types.js";
+import { ListPage } from "./ListPage.js";
+import { RefundModal } from "./Table.js";
+import { HttpStatusCode } from "@gnu-taler/taler-util";
+import { JumpToElementById } from 
"../../../../components/form/JumpToElementById.js";
+
+interface Props {
+  onUnauthorized: () => VNode;
+  onLoadError: (error: HttpError<MerchantBackend.ErrorDetail>) => VNode;
+  onNotFound: () => VNode;
+  onSelect: (id: string) => void;
+  onCreate: () => void;
+}
+
+export default function OrderList({
+  onUnauthorized,
+  onLoadError,
+  onCreate,
+  onSelect,
+  onNotFound,
+}: Props): VNode {
+  const [filter, setFilter] = useState<InstanceOrderFilter>({ paid: "no" });
+  const [orderToBeRefunded, setOrderToBeRefunded] = useState<
+    MerchantBackend.Orders.OrderHistoryEntry | undefined
+  >(undefined);
+
+  const setNewDate = (date?: Date): void =>
+    setFilter((prev) => ({ ...prev, date }));
+
+  const result = useInstanceOrders(filter, setNewDate);
+  const { refundOrder, getPaymentURL } = useOrderAPI();
+
+  const [notif, setNotif] = useState<Notification | undefined>(undefined);
+
+  const { i18n } = useTranslationContext();
+
+  if (result.loading) return <Loading />;
+  if (!result.ok) {
+    if (
+      result.type === ErrorType.CLIENT &&
+      result.status === HttpStatusCode.Unauthorized
+    )
+      return onUnauthorized();
+    if (
+      result.type === ErrorType.CLIENT &&
+      result.status === HttpStatusCode.NotFound
+    )
+      return onNotFound();
+    return onLoadError(result);
+  }
+
+  const isNotPaidActive = filter.paid === "no" ? "is-active" : "";
+  const isPaidActive = filter.paid === "yes" && filter.wired === undefined ? 
"is-active" : "";
+  const isRefundedActive = filter.refunded === "yes" ? "is-active" : "";
+  const isNotWiredActive = filter.wired === "no" && filter.paid === "yes" ? 
"is-active" : "";
+  const isWiredActive = filter.wired === "yes" ? "is-active" : "";
+  const isAllActive =
+    filter.paid === undefined &&
+      filter.refunded === undefined &&
+      filter.wired === undefined
+      ? "is-active"
+      : "";
+
+  return (
+    <section class="section is-main-section">
+      <NotificationCard notification={notif} />
+
+      <JumpToElementById
+        testIfExist={getPaymentURL} 
+        onSelect={onSelect}
+        description={i18n.str`jump to order with the given product ID`}
+        palceholder={i18n.str`order id`}
+      />
+
+      <ListPage
+        orders={result.data.orders.map((o) => ({ ...o, id: o.order_id }))}
+        onLoadMoreBefore={result.loadMorePrev}
+        hasMoreBefore={!result.isReachingStart}
+        onLoadMoreAfter={result.loadMore}
+        hasMoreAfter={!result.isReachingEnd}
+        onSelectOrder={(order) => onSelect(order.id)}
+        onRefundOrder={(value) => setOrderToBeRefunded(value)}
+        isAllActive={isAllActive}
+        isNotWiredActive={isNotWiredActive}
+        isWiredActive={isWiredActive}
+        isPaidActive={isPaidActive}
+        isNotPaidActive={isNotPaidActive}
+        isRefundedActive={isRefundedActive}
+        jumpToDate={filter.date}
+        onCopyURL={(id) =>
+          getPaymentURL(id).then((resp) => copyToClipboard(resp.data))
+        }
+        onCreate={onCreate}
+        onSelectDate={setNewDate}
+        onShowAll={() => setFilter({})}
+        onShowNotPaid={() => setFilter({ paid: "no" })}
+        onShowPaid={() => setFilter({ paid: "yes" })}
+        onShowRefunded={() => setFilter({ refunded: "yes" })}
+        onShowNotWired={() => setFilter({ wired: "no", paid: "yes" })}
+        onShowWired={() => setFilter({ wired: "yes" })}
+      />
+
+      {orderToBeRefunded && (
+        <RefundModalForTable
+          id={orderToBeRefunded.order_id}
+          onCancel={() => setOrderToBeRefunded(undefined)}
+          onConfirm={(value) =>
+            refundOrder(orderToBeRefunded.order_id, value)
+              .then(() =>
+                setNotif({
+                  message: i18n.str`refund created successfully`,
+                  type: "SUCCESS",
+                }),
+              )
+              .catch((error) =>
+                setNotif({
+                  message: i18n.str`could not create the refund`,
+                  type: "ERROR",
+                  description: error.message,
+                }),
+              )
+              .then(() => setOrderToBeRefunded(undefined))
+          }
+          onLoadError={(error) => {
+            setNotif({
+              message: i18n.str`could not create the refund`,
+              type: "ERROR",
+              description: error.message,
+            });
+            setOrderToBeRefunded(undefined);
+            return <div />;
+          }}
+          onUnauthorized={onUnauthorized}
+          onNotFound={() => {
+            setNotif({
+              message: i18n.str`could not get the order to refund`,
+              type: "ERROR",
+              // description: error.message
+            });
+            setOrderToBeRefunded(undefined);
+            return <div />;
+          }}
+        />
+      )}
+    </section>
+  );
+}
+
+interface RefundProps {
+  id: string;
+  onUnauthorized: () => VNode;
+  onLoadError: (error: HttpError<MerchantBackend.ErrorDetail>) => VNode;
+  onNotFound: () => VNode;
+  onCancel: () => void;
+  onConfirm: (m: MerchantBackend.Orders.RefundRequest) => void;
+}
+
+function RefundModalForTable({
+  id,
+  onUnauthorized,
+  onLoadError,
+  onNotFound,
+  onConfirm,
+  onCancel,
+}: RefundProps): VNode {
+  const result = useOrderDetails(id);
+
+  if (result.loading) return <Loading />;
+  if (!result.ok) {
+    if (
+      result.type === ErrorType.CLIENT &&
+      result.status === HttpStatusCode.Unauthorized
+    )
+      return onUnauthorized();
+    if (
+      result.type === ErrorType.CLIENT &&
+      result.status === HttpStatusCode.NotFound
+    )
+      return onNotFound();
+    return onLoadError(result);
+  }
+
+  return (
+    <RefundModal
+      order={result.data}
+      onCancel={onCancel}
+      onConfirm={onConfirm}
+    />
+  );
+}
+
+async function copyToClipboard(text: string): Promise<void> {
+  return navigator.clipboard.writeText(text);
+}
diff --git 
a/packages/auditor-backoffice-ui/src/paths/instance/otp_devices/create/Create.stories.tsx
 
b/packages/auditor-backoffice-ui/src/paths/instance/otp_devices/create/Create.stories.tsx
new file mode 100644
index 000000000..26f851cc8
--- /dev/null
+++ 
b/packages/auditor-backoffice-ui/src/paths/instance/otp_devices/create/Create.stories.tsx
@@ -0,0 +1,28 @@
+/*
+ This file is part of GNU Taler
+ (C) 2021-2023 Taler Systems S.A.
+
+ GNU Taler is free software; you can redistribute it and/or modify it under the
+ terms of the GNU General Public License as published by the Free Software
+ Foundation; either version 3, or (at your option) any later version.
+
+ GNU Taler is distributed in the hope that it will be useful, but WITHOUT ANY
+ WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
+ A PARTICULAR PURPOSE.  See the GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License along with
+ GNU Taler; see the file COPYING.  If not, see <http://www.gnu.org/licenses/>
+ */
+
+/**
+ *
+ * @author Sebastian Javier Marchano (sebasjm)
+ */
+
+import { h, VNode, FunctionalComponent } from "preact";
+import { CreatePage as TestedComponent } from "./CreatePage.js";
+
+export default {
+  title: "Pages/OtpDevices/Create",
+  component: TestedComponent,
+};
diff --git 
a/packages/auditor-backoffice-ui/src/paths/instance/otp_devices/create/CreatePage.tsx
 
b/packages/auditor-backoffice-ui/src/paths/instance/otp_devices/create/CreatePage.tsx
new file mode 100644
index 000000000..5f1ae26a3
--- /dev/null
+++ 
b/packages/auditor-backoffice-ui/src/paths/instance/otp_devices/create/CreatePage.tsx
@@ -0,0 +1,180 @@
+/*
+ This file is part of GNU Taler
+ (C) 2021-2023 Taler Systems S.A.
+
+ GNU Taler is free software; you can redistribute it and/or modify it under the
+ terms of the GNU General Public License as published by the Free Software
+ Foundation; either version 3, or (at your option) any later version.
+
+ GNU Taler is distributed in the hope that it will be useful, but WITHOUT ANY
+ WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
+ A PARTICULAR PURPOSE.  See the GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License along with
+ GNU Taler; see the file COPYING.  If not, see <http://www.gnu.org/licenses/>
+ */
+
+/**
+ *
+ * @author Sebastian Javier Marchano (sebasjm)
+ */
+
+import { useTranslationContext } from "@gnu-taler/web-util/browser";
+import { Fragment, h, VNode } from "preact";
+import { useState } from "preact/hooks";
+import { AsyncButton } from "../../../../components/exception/AsyncButton.js";
+import {
+  FormErrors,
+  FormProvider,
+} from "../../../../components/form/FormProvider.js";
+import { Input } from "../../../../components/form/Input.js";
+import { InputCurrency } from "../../../../components/form/InputCurrency.js";
+import { InputDuration } from "../../../../components/form/InputDuration.js";
+import { InputNumber } from "../../../../components/form/InputNumber.js";
+import { useBackendContext } from "../../../../context/backend.js";
+import { MerchantBackend } from "../../../../declaration.js";
+import { InputSelector } from "../../../../components/form/InputSelector.js";
+import { InputWithAddon } from "../../../../components/form/InputWithAddon.js";
+import { isBase32RFC3548Charset, randomBase32Key } from 
"../../../../utils/crypto.js";
+import { QR } from "../../../../components/exception/QR.js";
+import { useInstanceContext } from "../../../../context/instance.js";
+
+type Entity = MerchantBackend.OTP.OtpDeviceAddDetails;
+
+interface Props {
+  onCreate: (d: Entity) => Promise<void>;
+  onBack?: () => void;
+}
+
+const algorithms = [0, 1, 2];
+const algorithmsNames = ["off", "30s 8d TOTP-SHA1", "30s 8d eTOTP-SHA1"];
+
+
+export function CreatePage({ onCreate, onBack }: Props): VNode {
+  const { i18n } = useTranslationContext();
+  const backend = useBackendContext();
+
+  const [state, setState] = useState<Partial<Entity>>({});
+
+  const [showKey, setShowKey] = useState(false);
+
+  const errors: FormErrors<Entity> = {
+    otp_device_id: !state.otp_device_id ? i18n.str`required`
+      : !/[a-zA-Z0-9]*/.test(state.otp_device_id)
+        ? i18n.str`no valid. only characters and numbers`
+        : undefined,
+    otp_algorithm: !state.otp_algorithm ? i18n.str`required` : undefined,
+    otp_key: !state.otp_key ? i18n.str`required` :
+      !isBase32RFC3548Charset(state.otp_key)
+        ? i18n.str`just letters and numbers from 2 to 7`
+        : state.otp_key.length !== 32
+          ? i18n.str`size of the key should be 32`
+          : undefined,
+    otp_device_description: !state.otp_device_description ? i18n.str`required`
+      : !/[a-zA-Z0-9]*/.test(state.otp_device_description)
+        ? i18n.str`no valid. only characters and numbers`
+        : undefined,
+
+  };
+
+  const hasErrors = Object.keys(errors).some(
+    (k) => (errors as any)[k] !== undefined,
+  );
+
+  const submitForm = () => {
+    if (hasErrors) return Promise.reject();
+    return onCreate(state as any);
+  };
+
+  return (
+    <div>
+      <section class="section is-main-section">
+        <div class="columns">
+          <div class="column" />
+          <div class="column is-four-fifths">
+            <FormProvider
+              object={state}
+              valueHandler={setState}
+              errors={errors}
+            >
+              <Input<Entity>
+                name="otp_device_id"
+                label={i18n.str`ID`}
+                tooltip={i18n.str`Internal id on the system`}
+              />
+              <Input<Entity>
+                name="otp_device_description"
+                label={i18n.str`Descripiton`}
+                tooltip={i18n.str`Useful to identify the device physically`}
+              />
+              <InputSelector<Entity>
+                name="otp_algorithm"
+                label={i18n.str`Verification algorithm`}
+                tooltip={i18n.str`Algorithm to use to verify transaction in 
offline mode`}
+                values={algorithms}
+                toStr={(v) => algorithmsNames[v]}
+                fromStr={(v) => Number(v)}
+              />
+              {state.otp_algorithm && state.otp_algorithm > 0 ? (
+                <Fragment>
+                  <InputWithAddon<Entity>
+                    expand
+                    name="otp_key"
+                    label={i18n.str`Device key`}
+                    inputType={showKey ? "text" : "password"}
+                    help="Be sure to be very hard to guess or use the random 
generator"
+                    tooltip={i18n.str`Your device need to have exactly the 
same value`}
+                    fromStr={(v) => v.toUpperCase()}
+                    addonAfterAction={() => {
+                      setShowKey(!showKey);
+                    }}
+                    addonAfter={
+                      <span class="icon" >
+                        {showKey ? (
+                          <i class="mdi mdi-eye" />
+                        ) : (
+                          <i class="mdi mdi-eye-off" />
+                        )}
+                      </span>
+                    }
+                    side={
+                      <button
+                        data-tooltip={i18n.str`generate random secret key`}
+                        class="button is-info mr-3"
+                        onClick={(e) => {
+                          setState((s) => ({ ...s, otp_key: randomBase32Key() 
}));
+                        }}
+                      >
+                        <i18n.Translate>random</i18n.Translate>
+                      </button>
+                    }
+                  />
+                </Fragment>
+              ) : undefined}
+            </FormProvider>
+
+            <div class="buttons is-right mt-5">
+              {onBack && (
+                <button class="button" onClick={onBack}>
+                  <i18n.Translate>Cancel</i18n.Translate>
+                </button>
+              )}
+              <AsyncButton
+                disabled={hasErrors}
+                data-tooltip={
+                  hasErrors
+                    ? i18n.str`Need to complete marked fields`
+                    : "confirm operation"
+                }
+                onClick={submitForm}
+              >
+                <i18n.Translate>Confirm</i18n.Translate>
+              </AsyncButton>
+            </div>
+          </div>
+          <div class="column" />
+        </div>
+      </section>
+    </div>
+  );
+}
diff --git 
a/packages/auditor-backoffice-ui/src/paths/instance/otp_devices/create/CreatedSuccessfully.tsx
 
b/packages/auditor-backoffice-ui/src/paths/instance/otp_devices/create/CreatedSuccessfully.tsx
new file mode 100644
index 000000000..db3842711
--- /dev/null
+++ 
b/packages/auditor-backoffice-ui/src/paths/instance/otp_devices/create/CreatedSuccessfully.tsx
@@ -0,0 +1,104 @@
+/*
+ This file is part of GNU Taler
+ (C) 2021-2023 Taler Systems S.A.
+
+ GNU Taler is free software; you can redistribute it and/or modify it under the
+ terms of the GNU General Public License as published by the Free Software
+ Foundation; either version 3, or (at your option) any later version.
+
+ GNU Taler is distributed in the hope that it will be useful, but WITHOUT ANY
+ WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
+ A PARTICULAR PURPOSE.  See the GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License along with
+ GNU Taler; see the file COPYING.  If not, see <http://www.gnu.org/licenses/>
+ */
+
+import { useTranslationContext } from "@gnu-taler/web-util/browser";
+import { Fragment, VNode, h } from "preact";
+import { QR } from "../../../../components/exception/QR.js";
+import { CreatedSuccessfully as Template } from 
"../../../../components/notifications/CreatedSuccessfully.js";
+import { useInstanceContext } from "../../../../context/instance.js";
+import { MerchantBackend } from "../../../../declaration.js";
+import { useBackendContext } from "../../../../context/backend.js";
+
+type Entity = MerchantBackend.OTP.OtpDeviceAddDetails;
+
+interface Props {
+  entity: Entity;
+  onConfirm: () => void;
+}
+
+function isNotUndefined<X>(x: X | undefined): x is X {
+  return !!x;
+}
+
+export function CreatedSuccessfully({
+  entity,
+  onConfirm,
+}: Props): VNode {
+  const { i18n } = useTranslationContext();
+  const { url: backendURL } = useBackendContext()
+  const { id: instanceId } = useInstanceContext();
+  const issuer = new URL(backendURL).hostname;
+  const qrText = 
`otpauth://totp/${instanceId}/${entity.otp_device_id}?issuer=${issuer}&algorithm=SHA1&digits=8&period=30&secret=${entity.otp_key}`;
+  const qrTextSafe = 
`otpauth://totp/${instanceId}/${entity.otp_device_id}?issuer=${issuer}&algorithm=SHA1&digits=8&period=30&secret=${entity.otp_key.substring(0,
 6)}...`;
+
+  return (
+    <Template onConfirm={onConfirm} >
+      <p class="is-size-5">
+        <i18n.Translate>
+          You can scan the next QR code with your device or safe the key 
before continue.
+        </i18n.Translate>
+      </p>
+      <div class="field is-horizontal">
+        <div class="field-label is-normal">
+          <label class="label">ID</label>
+        </div>
+        <div class="field-body is-flex-grow-3">
+          <div class="field">
+            <p class="control">
+              <input
+                readonly
+                class="input"
+                value={entity.otp_device_id}
+              />
+            </p>
+          </div>
+        </div>
+      </div>
+      <div class="field is-horizontal">
+        <div class="field-label is-normal">
+          <label 
class="label"><i18n.Translate>Description</i18n.Translate></label>
+        </div>
+        <div class="field-body is-flex-grow-3">
+          <div class="field">
+            <p class="control">
+              <input
+                class="input"
+                readonly
+                value={entity.otp_device_description}
+              />
+            </p>
+          </div>
+        </div>
+      </div>
+      <QR
+        text={qrText}
+      />
+      <div
+        style={{
+          color: "grey",
+          fontSize: "small",
+          width: 200,
+          textAlign: "center",
+          margin: "auto",
+          wordBreak: "break-all",
+        }}
+      >
+        {qrTextSafe}
+      </div>
+    </Template>
+  );
+}
+
diff --git 
a/packages/auditor-backoffice-ui/src/paths/instance/otp_devices/create/index.tsx
 
b/packages/auditor-backoffice-ui/src/paths/instance/otp_devices/create/index.tsx
new file mode 100644
index 000000000..648846793
--- /dev/null
+++ 
b/packages/auditor-backoffice-ui/src/paths/instance/otp_devices/create/index.tsx
@@ -0,0 +1,70 @@
+/*
+ This file is part of GNU Taler
+ (C) 2021-2023 Taler Systems S.A.
+
+ GNU Taler is free software; you can redistribute it and/or modify it under the
+ terms of the GNU General Public License as published by the Free Software
+ Foundation; either version 3, or (at your option) any later version.
+
+ GNU Taler is distributed in the hope that it will be useful, but WITHOUT ANY
+ WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
+ A PARTICULAR PURPOSE.  See the GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License along with
+ GNU Taler; see the file COPYING.  If not, see <http://www.gnu.org/licenses/>
+ */
+
+/**
+ *
+ * @author Sebastian Javier Marchano (sebasjm)
+ */
+
+import { useTranslationContext } from "@gnu-taler/web-util/browser";
+import { Fragment, h, VNode } from "preact";
+import { useState } from "preact/hooks";
+import { NotificationCard } from "../../../../components/menu/index.js";
+import { MerchantBackend } from "../../../../declaration.js";
+import { useWebhookAPI } from "../../../../hooks/webhooks.js";
+import { Notification } from "../../../../utils/types.js";
+import { CreatePage } from "./CreatePage.js";
+import { useOtpDeviceAPI } from "../../../../hooks/otp.js";
+import { CreatedSuccessfully } from "./CreatedSuccessfully.js";
+
+export type Entity = MerchantBackend.OTP.OtpDeviceAddDetails;
+interface Props {
+  onBack?: () => void;
+  onConfirm: () => void;
+}
+
+export default function CreateValidator({ onConfirm, onBack }: Props): VNode {
+  const { createOtpDevice } = useOtpDeviceAPI();
+  const [notif, setNotif] = useState<Notification | undefined>(undefined);
+  const { i18n } = useTranslationContext();
+  const [created, setCreated] = 
useState<MerchantBackend.OTP.OtpDeviceAddDetails | null>(null)
+
+  if (created) {
+    return <CreatedSuccessfully entity={created} onConfirm={onConfirm} />
+  }
+
+  return (
+    <>
+      <NotificationCard notification={notif} />
+      <CreatePage
+        onBack={onBack}
+        onCreate={(request: Entity) => {
+          return createOtpDevice(request)
+            .then((d) => {
+              setCreated(request)
+            })
+            .catch((error) => {
+              setNotif({
+                message: i18n.str`could not create device`,
+                type: "ERROR",
+                description: error.message,
+              });
+            });
+        }}
+      />
+    </>
+  );
+}
diff --git 
a/packages/auditor-backoffice-ui/src/paths/instance/otp_devices/list/List.stories.tsx
 
b/packages/auditor-backoffice-ui/src/paths/instance/otp_devices/list/List.stories.tsx
new file mode 100644
index 000000000..b18049674
--- /dev/null
+++ 
b/packages/auditor-backoffice-ui/src/paths/instance/otp_devices/list/List.stories.tsx
@@ -0,0 +1,28 @@
+/*
+ This file is part of GNU Taler
+ (C) 2021-2023 Taler Systems S.A.
+
+ GNU Taler is free software; you can redistribute it and/or modify it under the
+ terms of the GNU General Public License as published by the Free Software
+ Foundation; either version 3, or (at your option) any later version.
+
+ GNU Taler is distributed in the hope that it will be useful, but WITHOUT ANY
+ WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
+ A PARTICULAR PURPOSE.  See the GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License along with
+ GNU Taler; see the file COPYING.  If not, see <http://www.gnu.org/licenses/>
+ */
+
+/**
+ *
+ * @author Sebastian Javier Marchano (sebasjm)
+ */
+
+import { FunctionalComponent, h } from "preact";
+import { ListPage as TestedComponent } from "./ListPage.js";
+
+export default {
+  title: "Pages/OtpDevices/List",
+  component: TestedComponent,
+};
diff --git 
a/packages/auditor-backoffice-ui/src/paths/instance/otp_devices/list/ListPage.tsx
 
b/packages/auditor-backoffice-ui/src/paths/instance/otp_devices/list/ListPage.tsx
new file mode 100644
index 000000000..4efee9781
--- /dev/null
+++ 
b/packages/auditor-backoffice-ui/src/paths/instance/otp_devices/list/ListPage.tsx
@@ -0,0 +1,64 @@
+/*
+ This file is part of GNU Taler
+ (C) 2021-2023 Taler Systems S.A.
+
+ GNU Taler is free software; you can redistribute it and/or modify it under the
+ terms of the GNU General Public License as published by the Free Software
+ Foundation; either version 3, or (at your option) any later version.
+
+ GNU Taler is distributed in the hope that it will be useful, but WITHOUT ANY
+ WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
+ A PARTICULAR PURPOSE.  See the GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License along with
+ GNU Taler; see the file COPYING.  If not, see <http://www.gnu.org/licenses/>
+ */
+
+/**
+ *
+ * @author Sebastian Javier Marchano (sebasjm)
+ */
+
+import { h, VNode } from "preact";
+import { MerchantBackend } from "../../../../declaration.js";
+import { useTranslationContext } from "@gnu-taler/web-util/browser";
+import { CardTable } from "./Table.js";
+
+export interface Props {
+  devices: MerchantBackend.OTP.OtpDeviceEntry[];
+  onLoadMoreBefore?: () => void;
+  onLoadMoreAfter?: () => void;
+  onCreate: () => void;
+  onDelete: (e: MerchantBackend.OTP.OtpDeviceEntry) => void;
+  onSelect: (e: MerchantBackend.OTP.OtpDeviceEntry) => void;
+}
+
+export function ListPage({
+  devices,
+  onCreate,
+  onDelete,
+  onSelect,
+  onLoadMoreBefore,
+  onLoadMoreAfter,
+}: Props): VNode {
+  const form = { payto_uri: "" };
+
+  const { i18n } = useTranslationContext();
+  return (
+    <section class="section is-main-section">
+      <CardTable
+        devices={devices.map((o) => ({
+          ...o,
+          id: String(o.otp_device_id),
+        }))}
+        onCreate={onCreate}
+        onDelete={onDelete}
+        onSelect={onSelect}
+        onLoadMoreBefore={onLoadMoreBefore}
+        hasMoreBefore={!onLoadMoreBefore}
+        onLoadMoreAfter={onLoadMoreAfter}
+        hasMoreAfter={!onLoadMoreAfter}
+      />
+    </section>
+  );
+}
diff --git 
a/packages/auditor-backoffice-ui/src/paths/instance/otp_devices/list/Table.tsx 
b/packages/auditor-backoffice-ui/src/paths/instance/otp_devices/list/Table.tsx
new file mode 100644
index 000000000..0c28027fe
--- /dev/null
+++ 
b/packages/auditor-backoffice-ui/src/paths/instance/otp_devices/list/Table.tsx
@@ -0,0 +1,211 @@
+/*
+ This file is part of GNU Taler
+ (C) 2021-2023 Taler Systems S.A.
+
+ GNU Taler is free software; you can redistribute it and/or modify it under the
+ terms of the GNU General Public License as published by the Free Software
+ Foundation; either version 3, or (at your option) any later version.
+
+ GNU Taler is distributed in the hope that it will be useful, but WITHOUT ANY
+ WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
+ A PARTICULAR PURPOSE.  See the GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License along with
+ GNU Taler; see the file COPYING.  If not, see <http://www.gnu.org/licenses/>
+ */
+
+/**
+ *
+ * @author Sebastian Javier Marchano (sebasjm)
+ */
+
+import { useTranslationContext } from "@gnu-taler/web-util/browser";
+import { h, VNode } from "preact";
+import { StateUpdater, useState } from "preact/hooks";
+import { MerchantBackend } from "../../../../declaration.js";
+
+type Entity = MerchantBackend.OTP.OtpDeviceEntry;
+
+interface Props {
+  devices: Entity[];
+  onDelete: (e: Entity) => void;
+  onSelect: (e: Entity) => void;
+  onCreate: () => void;
+  onLoadMoreBefore?: () => void;
+  hasMoreBefore?: boolean;
+  hasMoreAfter?: boolean;
+  onLoadMoreAfter?: () => void;
+}
+
+export function CardTable({
+  devices,
+  onCreate,
+  onDelete,
+  onSelect,
+  onLoadMoreAfter,
+  onLoadMoreBefore,
+  hasMoreAfter,
+  hasMoreBefore,
+}: Props): VNode {
+  const [rowSelection, rowSelectionHandler] = useState<string[]>([]);
+
+  const { i18n } = useTranslationContext();
+
+  return (
+    <div class="card has-table">
+      <header class="card-header">
+        <p class="card-header-title">
+          <span class="icon">
+            <i class="mdi mdi-newspaper" />
+          </span>
+          <i18n.Translate>OTP Devices</i18n.Translate>
+        </p>
+        <div class="card-header-icon" aria-label="more options">
+          <span
+            class="has-tooltip-left"
+            data-tooltip={i18n.str`add new devices`}
+          >
+            <button class="button is-info" type="button" onClick={onCreate}>
+              <span class="icon is-small">
+                <i class="mdi mdi-plus mdi-36px" />
+              </span>
+            </button>
+          </span>
+        </div>
+      </header>
+      <div class="card-content">
+        <div class="b-table has-pagination">
+          <div class="table-wrapper has-mobile-cards">
+            {devices.length > 0 ? (
+              <Table
+                instances={devices}
+                onDelete={onDelete}
+                onSelect={onSelect}
+                rowSelection={rowSelection}
+                rowSelectionHandler={rowSelectionHandler}
+                onLoadMoreAfter={onLoadMoreAfter}
+                onLoadMoreBefore={onLoadMoreBefore}
+                hasMoreAfter={hasMoreAfter}
+                hasMoreBefore={hasMoreBefore}
+              />
+            ) : (
+              <EmptyTable />
+            )}
+          </div>
+        </div>
+      </div>
+    </div>
+  );
+}
+interface TableProps {
+  rowSelection: string[];
+  instances: Entity[];
+  onDelete: (e: Entity) => void;
+  onSelect: (e: Entity) => void;
+  rowSelectionHandler: StateUpdater<string[]>;
+  onLoadMoreBefore?: () => void;
+  hasMoreBefore?: boolean;
+  hasMoreAfter?: boolean;
+  onLoadMoreAfter?: () => void;
+}
+
+function toggleSelected<T>(id: T): (prev: T[]) => T[] {
+  return (prev: T[]): T[] =>
+    prev.indexOf(id) == -1 ? [...prev, id] : prev.filter((e) => e != id);
+}
+
+function Table({
+  instances,
+  onLoadMoreAfter,
+  onDelete,
+  onSelect,
+  onLoadMoreBefore,
+  hasMoreAfter,
+  hasMoreBefore,
+}: TableProps): VNode {
+  const { i18n } = useTranslationContext();
+  return (
+    <div class="table-container">
+      {hasMoreBefore && (
+        <button
+          class="button is-fullwidth"
+          data-tooltip={i18n.str`load more devices before the first one`}
+          onClick={onLoadMoreBefore}
+        >
+          <i18n.Translate>load newer devices</i18n.Translate>
+        </button>
+      )}
+      <table class="table is-fullwidth is-striped is-hoverable is-fullwidth">
+        <thead>
+          <tr>
+            <th>
+              <i18n.Translate>ID</i18n.Translate>
+            </th>
+            <th>
+              <i18n.Translate>Description</i18n.Translate>
+            </th>
+            <th />
+          </tr>
+        </thead>
+        <tbody>
+          {instances.map((i) => {
+            return (
+              <tr key={i.otp_device_id}>
+                <td
+                  onClick={(): void => onSelect(i)}
+                  style={{ cursor: "pointer" }}
+                >
+                  {i.otp_device_id}
+                </td>
+                <td
+                  onClick={(): void => onSelect(i)}
+                  style={{ cursor: "pointer" }}
+                >
+                  {i.otp_device_id}
+                </td>
+                <td class="is-actions-cell right-sticky">
+                  <div class="buttons is-right">
+                    <button
+                      class="button is-danger is-small has-tooltip-left"
+                      data-tooltip={i18n.str`delete selected devices from the 
database`}
+                      onClick={() => onDelete(i)}
+                    >
+                      Delete
+                    </button>
+                  </div>
+                </td>
+              </tr>
+            );
+          })}
+        </tbody>
+      </table>
+      {hasMoreAfter && (
+        <button
+          class="button is-fullwidth"
+          data-tooltip={i18n.str`load more devices after the last one`}
+          onClick={onLoadMoreAfter}
+        >
+          <i18n.Translate>load older devices</i18n.Translate>
+        </button>
+      )}
+    </div>
+  );
+}
+
+function EmptyTable(): VNode {
+  const { i18n } = useTranslationContext();
+  return (
+    <div class="content has-text-grey has-text-centered">
+      <p>
+        <span class="icon is-large">
+          <i class="mdi mdi-emoticon-sad mdi-48px" />
+        </span>
+      </p>
+      <p>
+        <i18n.Translate>
+          There is no devices yet, add more pressing the + sign
+        </i18n.Translate>
+      </p>
+    </div>
+  );
+}
diff --git 
a/packages/auditor-backoffice-ui/src/paths/instance/otp_devices/list/index.tsx 
b/packages/auditor-backoffice-ui/src/paths/instance/otp_devices/list/index.tsx
new file mode 100644
index 000000000..2aae8738a
--- /dev/null
+++ 
b/packages/auditor-backoffice-ui/src/paths/instance/otp_devices/list/index.tsx
@@ -0,0 +1,106 @@
+/*
+ This file is part of GNU Taler
+ (C) 2021-2023 Taler Systems S.A.
+
+ GNU Taler is free software; you can redistribute it and/or modify it under the
+ terms of the GNU General Public License as published by the Free Software
+ Foundation; either version 3, or (at your option) any later version.
+
+ GNU Taler is distributed in the hope that it will be useful, but WITHOUT ANY
+ WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
+ A PARTICULAR PURPOSE.  See the GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License along with
+ GNU Taler; see the file COPYING.  If not, see <http://www.gnu.org/licenses/>
+ */
+
+/**
+ *
+ * @author Sebastian Javier Marchano (sebasjm)
+ */
+
+import { HttpStatusCode } from "@gnu-taler/taler-util";
+import {
+  ErrorType,
+  HttpError,
+  useTranslationContext,
+} from "@gnu-taler/web-util/browser";
+import { Fragment, VNode, h } from "preact";
+import { useState } from "preact/hooks";
+import { Loading } from "../../../../components/exception/loading.js";
+import { NotificationCard } from "../../../../components/menu/index.js";
+import { MerchantBackend } from "../../../../declaration.js";
+import { useInstanceOtpDevices, useOtpDeviceAPI } from 
"../../../../hooks/otp.js";
+import { Notification } from "../../../../utils/types.js";
+import { ListPage } from "./ListPage.js";
+
+interface Props {
+  onUnauthorized: () => VNode;
+  onLoadError: (error: HttpError<MerchantBackend.ErrorDetail>) => VNode;
+  onNotFound: () => VNode;
+  onCreate: () => void;
+  onSelect: (id: string) => void;
+}
+
+export default function ListOtpDevices({
+  onUnauthorized,
+  onLoadError,
+  onCreate,
+  onSelect,
+  onNotFound,
+}: Props): VNode {
+  const [position, setPosition] = useState<string | undefined>(undefined);
+  const { i18n } = useTranslationContext();
+  const [notif, setNotif] = useState<Notification | undefined>(undefined);
+  const { deleteOtpDevice } = useOtpDeviceAPI();
+  const result = useInstanceOtpDevices({ position }, (id) => setPosition(id));
+
+  if (result.loading) return <Loading />;
+  if (!result.ok) {
+    if (
+      result.type === ErrorType.CLIENT &&
+      result.status === HttpStatusCode.Unauthorized
+    )
+      return onUnauthorized();
+    if (
+      result.type === ErrorType.CLIENT &&
+      result.status === HttpStatusCode.NotFound
+    )
+      return onNotFound();
+    return onLoadError(result);
+  }
+
+  return (
+    <Fragment>
+      <NotificationCard notification={notif} />
+
+      <ListPage
+        devices={result.data.otp_devices}
+        onLoadMoreBefore={
+          result.isReachingStart ? result.loadMorePrev : undefined
+        }
+        onLoadMoreAfter={result.isReachingEnd ? result.loadMore : undefined}
+        onCreate={onCreate}
+        onSelect={(e) => {
+          onSelect(e.otp_device_id);
+        }}
+        onDelete={(e: MerchantBackend.OTP.OtpDeviceEntry) =>
+          deleteOtpDevice(e.otp_device_id)
+            .then(() =>
+              setNotif({
+                message: i18n.str`validator delete successfully`,
+                type: "SUCCESS",
+              }),
+            )
+            .catch((error) =>
+              setNotif({
+                message: i18n.str`could not delete the validator`,
+                type: "ERROR",
+                description: error.message,
+              }),
+            )
+        }
+      />
+    </Fragment>
+  );
+}
diff --git 
a/packages/auditor-backoffice-ui/src/paths/instance/otp_devices/update/Update.stories.tsx
 
b/packages/auditor-backoffice-ui/src/paths/instance/otp_devices/update/Update.stories.tsx
new file mode 100644
index 000000000..d6b1d65e0
--- /dev/null
+++ 
b/packages/auditor-backoffice-ui/src/paths/instance/otp_devices/update/Update.stories.tsx
@@ -0,0 +1,32 @@
+/*
+ This file is part of GNU Taler
+ (C) 2021-2023 Taler Systems S.A.
+
+ GNU Taler is free software; you can redistribute it and/or modify it under the
+ terms of the GNU General Public License as published by the Free Software
+ Foundation; either version 3, or (at your option) any later version.
+
+ GNU Taler is distributed in the hope that it will be useful, but WITHOUT ANY
+ WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
+ A PARTICULAR PURPOSE.  See the GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License along with
+ GNU Taler; see the file COPYING.  If not, see <http://www.gnu.org/licenses/>
+ */
+
+/**
+ *
+ * @author Sebastian Javier Marchano (sebasjm)
+ */
+
+import { h, VNode, FunctionalComponent } from "preact";
+import { UpdatePage as TestedComponent } from "./UpdatePage.js";
+
+export default {
+  title: "Pages/OtpDevices/Update",
+  component: TestedComponent,
+  argTypes: {
+    onUpdate: { action: "onUpdate" },
+    onBack: { action: "onBack" },
+  },
+};
diff --git 
a/packages/auditor-backoffice-ui/src/paths/instance/otp_devices/update/UpdatePage.tsx
 
b/packages/auditor-backoffice-ui/src/paths/instance/otp_devices/update/UpdatePage.tsx
new file mode 100644
index 000000000..b82807cc7
--- /dev/null
+++ 
b/packages/auditor-backoffice-ui/src/paths/instance/otp_devices/update/UpdatePage.tsx
@@ -0,0 +1,171 @@
+/*
+ This file is part of GNU Taler
+ (C) 2021-2023 Taler Systems S.A.
+
+ GNU Taler is free software; you can redistribute it and/or modify it under the
+ terms of the GNU General Public License as published by the Free Software
+ Foundation; either version 3, or (at your option) any later version.
+
+ GNU Taler is distributed in the hope that it will be useful, but WITHOUT ANY
+ WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
+ A PARTICULAR PURPOSE.  See the GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License along with
+ GNU Taler; see the file COPYING.  If not, see <http://www.gnu.org/licenses/>
+ */
+
+/**
+ *
+ * @author Sebastian Javier Marchano (sebasjm)
+ */
+
+import { useTranslationContext } from "@gnu-taler/web-util/browser";
+import { Fragment, h, VNode } from "preact";
+import { useState } from "preact/hooks";
+import { AsyncButton } from "../../../../components/exception/AsyncButton.js";
+import {
+  FormErrors,
+  FormProvider,
+} from "../../../../components/form/FormProvider.js";
+import { Input } from "../../../../components/form/Input.js";
+import { MerchantBackend, WithId } from "../../../../declaration.js";
+import { InputSelector } from "../../../../components/form/InputSelector.js";
+import { InputWithAddon } from "../../../../components/form/InputWithAddon.js";
+import { randomBase32Key } from "../../../../utils/crypto.js";
+
+type Entity = MerchantBackend.OTP.OtpDevicePatchDetails & WithId;
+
+interface Props {
+  onUpdate: (d: Entity) => Promise<void>;
+  onBack?: () => void;
+  device: Entity;
+}
+const algorithms = [0, 1, 2];
+const algorithmsNames = ["off", "30s 8d TOTP-SHA1", "30s 8d eTOTP-SHA1"];
+export function UpdatePage({ device, onUpdate, onBack }: Props): VNode {
+  const { i18n } = useTranslationContext();
+
+  const [state, setState] = useState<Partial<Entity>>(device);
+  const [showKey, setShowKey] = useState(false);
+
+  const errors: FormErrors<Entity> = {
+  };
+
+  const hasErrors = Object.keys(errors).some(
+    (k) => (errors as any)[k] !== undefined,
+  );
+
+  const submitForm = () => {
+    if (hasErrors) return Promise.reject();
+    return onUpdate(state as any);
+  };
+
+  return (
+    <div>
+      <section class="section">
+        <section class="hero is-hero-bar">
+          <div class="hero-body">
+            <div class="level">
+              <div class="level-left">
+                <div class="level-item">
+                  <span class="is-size-4">
+                    Device: <b>{device.id}</b>
+                  </span>
+                </div>
+              </div>
+            </div>
+          </div>
+        </section>
+        <hr />
+
+        <section class="section is-main-section">
+          <div class="columns">
+            <div class="column is-four-fifths">
+              <FormProvider
+                object={state}
+                valueHandler={setState}
+                errors={errors}
+              >
+                <Input<Entity>
+                  name="otp_device_description"
+                  label={i18n.str`Description`}
+                  tooltip={i18n.str`Useful to identify the device physically`}
+                />
+                <InputSelector<Entity>
+                  name="otp_algorithm"
+                  label={i18n.str`Verification algorithm`}
+                  tooltip={i18n.str`Algorithm to use to verify transaction in 
offline mode`}
+                  values={algorithms}
+                  toStr={(v) => algorithmsNames[v]}
+                  fromStr={(v) => Number(v)}
+                />
+                {state.otp_algorithm && state.otp_algorithm > 0 ? (
+                  <Fragment>
+                    <InputWithAddon<Entity>
+                      name="otp_key"
+                      label={i18n.str`Device key`}
+                      readonly={state.otp_key === undefined}
+                      inputType={showKey ? "text" : "password"}
+                      help={state.otp_key === undefined ? "Not modified" : "Be 
sure to be very hard to guess or use the random generator"}
+                      tooltip={i18n.str`Your device need to have exactly the 
same value`}
+                      fromStr={(v) => v.toUpperCase()}
+                      addonAfterAction={() => {
+                        setShowKey(!showKey);
+                      }}
+                      addonAfter={
+                        <span class="icon" onClick={() => {
+                          setShowKey(!showKey);
+                        }}>
+                          {showKey ? (
+                            <i class="mdi mdi-eye" />
+                          ) : (
+                            <i class="mdi mdi-eye-off" />
+                          )}
+                        </span>
+                      }
+                      side={
+                        state.otp_key === undefined ? <button
+
+                          onClick={(e) => {
+                            setState((s) => ({ ...s, otp_key: "" }));
+                          }}
+                          class="button">change key</button> :
+                          <button
+                            data-tooltip={i18n.str`generate random secret key`}
+                            class="button is-info mr-3"
+                            onClick={(e) => {
+                              setState((s) => ({ ...s, otp_key: 
randomBase32Key() }));
+                            }}
+                          >
+                            <i18n.Translate>random</i18n.Translate>
+                          </button>
+                      }
+                    />
+                  </Fragment>
+                ) : undefined}              </FormProvider>
+
+              <div class="buttons is-right mt-5">
+                {onBack && (
+                  <button class="button" onClick={onBack}>
+                    <i18n.Translate>Cancel</i18n.Translate>
+                  </button>
+                )}
+                <AsyncButton
+                  disabled={hasErrors}
+                  data-tooltip={
+                    hasErrors
+                      ? i18n.str`Need to complete marked fields`
+                      : "confirm operation"
+                  }
+                  onClick={submitForm}
+                >
+                  <i18n.Translate>Confirm</i18n.Translate>
+                </AsyncButton>
+              </div>
+            </div>
+          </div>
+        </section>
+      </section>
+    </div>
+  );
+}
diff --git 
a/packages/auditor-backoffice-ui/src/paths/instance/otp_devices/update/index.tsx
 
b/packages/auditor-backoffice-ui/src/paths/instance/otp_devices/update/index.tsx
new file mode 100644
index 000000000..52f6c6c29
--- /dev/null
+++ 
b/packages/auditor-backoffice-ui/src/paths/instance/otp_devices/update/index.tsx
@@ -0,0 +1,102 @@
+/*
+ This file is part of GNU Taler
+ (C) 2021-2023 Taler Systems S.A.
+
+ GNU Taler is free software; you can redistribute it and/or modify it under the
+ terms of the GNU General Public License as published by the Free Software
+ Foundation; either version 3, or (at your option) any later version.
+
+ GNU Taler is distributed in the hope that it will be useful, but WITHOUT ANY
+ WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
+ A PARTICULAR PURPOSE.  See the GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License along with
+ GNU Taler; see the file COPYING.  If not, see <http://www.gnu.org/licenses/>
+ */
+
+/**
+ *
+ * @author Sebastian Javier Marchano (sebasjm)
+ */
+
+import {
+  ErrorType,
+  HttpError,
+  useTranslationContext,
+} from "@gnu-taler/web-util/browser";
+import { Fragment, h, VNode } from "preact";
+import { useState } from "preact/hooks";
+import { Loading } from "../../../../components/exception/loading.js";
+import { NotificationCard } from "../../../../components/menu/index.js";
+import { MerchantBackend, WithId } from "../../../../declaration.js";
+import { Notification } from "../../../../utils/types.js";
+import { UpdatePage } from "./UpdatePage.js";
+import { HttpStatusCode } from "@gnu-taler/taler-util";
+import { useOtpDeviceAPI, useOtpDeviceDetails } from 
"../../../../hooks/otp.js";
+
+export type Entity = MerchantBackend.OTP.OtpDevicePatchDetails & WithId;
+
+interface Props {
+  onBack?: () => void;
+  onConfirm: () => void;
+  onUnauthorized: () => VNode;
+  onNotFound: () => VNode;
+  onLoadError: (e: HttpError<MerchantBackend.ErrorDetail>) => VNode;
+  vid: string;
+}
+export default function UpdateValidator({
+  vid,
+  onConfirm,
+  onBack,
+  onUnauthorized,
+  onNotFound,
+  onLoadError,
+}: Props): VNode {
+  const { updateOtpDevice } = useOtpDeviceAPI();
+  const result = useOtpDeviceDetails(vid);
+  const [notif, setNotif] = useState<Notification | undefined>(undefined);
+
+  const { i18n } = useTranslationContext();
+
+  if (result.loading) return <Loading />;
+  if (!result.ok) {
+    if (
+      result.type === ErrorType.CLIENT &&
+      result.status === HttpStatusCode.Unauthorized
+    )
+      return onUnauthorized();
+    if (
+      result.type === ErrorType.CLIENT &&
+      result.status === HttpStatusCode.NotFound
+    )
+      return onNotFound();
+    return onLoadError(result);
+  }
+
+  return (
+    <Fragment>
+      <NotificationCard notification={notif} />
+      <UpdatePage
+        device={{
+          id: vid,
+          otp_algorithm: result.data.otp_algorithm,
+          otp_device_description: result.data.device_description,
+          otp_key: undefined,
+          otp_ctr: result.data.otp_ctr
+        }}
+        onBack={onBack}
+        onUpdate={(data) => {
+          return updateOtpDevice(vid, data)
+            .then(onConfirm)
+            .catch((error) => {
+              setNotif({
+                message: i18n.str`could not update template`,
+                type: "ERROR",
+                description: error.message,
+              });
+            });
+        }}
+      />
+    </Fragment>
+  );
+}
diff --git 
a/packages/auditor-backoffice-ui/src/paths/instance/products/create/Create.stories.tsx
 
b/packages/auditor-backoffice-ui/src/paths/instance/products/create/Create.stories.tsx
new file mode 100644
index 000000000..2fc0819bb
--- /dev/null
+++ 
b/packages/auditor-backoffice-ui/src/paths/instance/products/create/Create.stories.tsx
@@ -0,0 +1,43 @@
+/*
+ This file is part of GNU Taler
+ (C) 2021-2023 Taler Systems S.A.
+
+ GNU Taler is free software; you can redistribute it and/or modify it under the
+ terms of the GNU General Public License as published by the Free Software
+ Foundation; either version 3, or (at your option) any later version.
+
+ GNU Taler is distributed in the hope that it will be useful, but WITHOUT ANY
+ WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
+ A PARTICULAR PURPOSE.  See the GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License along with
+ GNU Taler; see the file COPYING.  If not, see <http://www.gnu.org/licenses/>
+ */
+
+/**
+ *
+ * @author Sebastian Javier Marchano (sebasjm)
+ */
+
+import { h, VNode, FunctionalComponent } from "preact";
+import { CreatePage as TestedComponent } from "./CreatePage.js";
+
+export default {
+  title: "Pages/Product/Create",
+  component: TestedComponent,
+  argTypes: {
+    onCreate: { action: "onCreate" },
+    onBack: { action: "onBack" },
+  },
+};
+
+function createExample<Props>(
+  Component: FunctionalComponent<Props>,
+  props: Partial<Props>,
+) {
+  const r = (args: any) => <Component {...args} />;
+  r.args = props;
+  return r;
+}
+
+export const Example = createExample(TestedComponent, {});
diff --git 
a/packages/auditor-backoffice-ui/src/paths/instance/products/create/CreatePage.tsx
 
b/packages/auditor-backoffice-ui/src/paths/instance/products/create/CreatePage.tsx
new file mode 100644
index 000000000..becaf8f3a
--- /dev/null
+++ 
b/packages/auditor-backoffice-ui/src/paths/instance/products/create/CreatePage.tsx
@@ -0,0 +1,80 @@
+/*
+ This file is part of GNU Taler
+ (C) 2021-2023 Taler Systems S.A.
+
+ GNU Taler is free software; you can redistribute it and/or modify it under the
+ terms of the GNU General Public License as published by the Free Software
+ Foundation; either version 3, or (at your option) any later version.
+
+ GNU Taler is distributed in the hope that it will be useful, but WITHOUT ANY
+ WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
+ A PARTICULAR PURPOSE.  See the GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License along with
+ GNU Taler; see the file COPYING.  If not, see <http://www.gnu.org/licenses/>
+ */
+
+/**
+ *
+ * @author Sebastian Javier Marchano (sebasjm)
+ */
+
+import { useTranslationContext } from "@gnu-taler/web-util/browser";
+import { h, VNode } from "preact";
+import { AsyncButton } from "../../../../components/exception/AsyncButton.js";
+import { ProductForm } from "../../../../components/product/ProductForm.js";
+import { MerchantBackend } from "../../../../declaration.js";
+import { useListener } from "../../../../hooks/listener.js";
+
+type Entity = MerchantBackend.Products.ProductAddDetail & {
+  product_id: string;
+};
+
+interface Props {
+  onCreate: (d: Entity) => Promise<void>;
+  onBack?: () => void;
+}
+
+export function CreatePage({ onCreate, onBack }: Props): VNode {
+  const [submitForm, addFormSubmitter] = useListener<Entity | undefined>(
+    (result) => {
+      if (result) return onCreate(result);
+      return Promise.reject();
+    },
+  );
+
+  const { i18n } = useTranslationContext();
+
+  return (
+    <div>
+      <section class="section is-main-section">
+        <div class="columns">
+          <div class="column" />
+          <div class="column is-four-fifths">
+            <ProductForm onSubscribe={addFormSubmitter} />
+
+            <div class="buttons is-right mt-5">
+              {onBack && (
+                <button class="button" onClick={onBack}>
+                  <i18n.Translate>Cancel</i18n.Translate>
+                </button>
+              )}
+              <AsyncButton
+                onClick={submitForm}
+                data-tooltip={
+                  !submitForm
+                    ? i18n.str`Need to complete marked fields`
+                    : "confirm operation"
+                }
+                disabled={!submitForm}
+              >
+                <i18n.Translate>Confirm</i18n.Translate>
+              </AsyncButton>
+            </div>
+          </div>
+          <div class="column" />
+        </div>
+      </section>
+    </div>
+  );
+}
diff --git 
a/packages/auditor-backoffice-ui/src/paths/instance/products/create/CreatedSuccessfully.tsx
 
b/packages/auditor-backoffice-ui/src/paths/instance/products/create/CreatedSuccessfully.tsx
new file mode 100644
index 000000000..6b02430cc
--- /dev/null
+++ 
b/packages/auditor-backoffice-ui/src/paths/instance/products/create/CreatedSuccessfully.tsx
@@ -0,0 +1,72 @@
+/*
+ This file is part of GNU Taler
+ (C) 2021-2023 Taler Systems S.A.
+
+ GNU Taler is free software; you can redistribute it and/or modify it under the
+ terms of the GNU General Public License as published by the Free Software
+ Foundation; either version 3, or (at your option) any later version.
+
+ GNU Taler is distributed in the hope that it will be useful, but WITHOUT ANY
+ WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
+ A PARTICULAR PURPOSE.  See the GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License along with
+ GNU Taler; see the file COPYING.  If not, see <http://www.gnu.org/licenses/>
+ */
+import { h, VNode } from "preact";
+import { CreatedSuccessfully as Template } from 
"../../../../components/notifications/CreatedSuccessfully.js";
+import { Entity } from "./index.js";
+import emptyImage from "../../assets/empty.png";
+
+interface Props {
+  entity: Entity;
+  onConfirm: () => void;
+  onCreateAnother?: () => void;
+}
+
+export function CreatedSuccessfully({
+  entity,
+  onConfirm,
+  onCreateAnother,
+}: Props): VNode {
+  return (
+    <Template onConfirm={onConfirm} onCreateAnother={onCreateAnother}>
+      <div class="field is-horizontal">
+        <div class="field-label is-normal">
+          <label class="label">Image</label>
+        </div>
+        <div class="field-body is-flex-grow-3">
+          <div class="field">
+            <p class="control">
+              <img src={entity.image} style={{ width: 200, height: 200 }} />
+            </p>
+          </div>
+        </div>
+      </div>
+      <div class="field is-horizontal">
+        <div class="field-label is-normal">
+          <label class="label">Description</label>
+        </div>
+        <div class="field-body is-flex-grow-3">
+          <div class="field">
+            <p class="control">
+              <textarea class="input" readonly value={entity.description} />
+            </p>
+          </div>
+        </div>
+      </div>
+      <div class="field is-horizontal">
+        <div class="field-label is-normal">
+          <label class="label">Price</label>
+        </div>
+        <div class="field-body is-flex-grow-3">
+          <div class="field">
+            <p class="control">
+              <input class="input" readonly value={entity.price} />
+            </p>
+          </div>
+        </div>
+      </div>
+    </Template>
+  );
+}
diff --git 
a/packages/auditor-backoffice-ui/src/paths/instance/products/create/index.tsx 
b/packages/auditor-backoffice-ui/src/paths/instance/products/create/index.tsx
new file mode 100644
index 000000000..775690bd1
--- /dev/null
+++ 
b/packages/auditor-backoffice-ui/src/paths/instance/products/create/index.tsx
@@ -0,0 +1,60 @@
+/*
+ This file is part of GNU Taler
+ (C) 2021-2023 Taler Systems S.A.
+
+ GNU Taler is free software; you can redistribute it and/or modify it under the
+ terms of the GNU General Public License as published by the Free Software
+ Foundation; either version 3, or (at your option) any later version.
+
+ GNU Taler is distributed in the hope that it will be useful, but WITHOUT ANY
+ WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
+ A PARTICULAR PURPOSE.  See the GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License along with
+ GNU Taler; see the file COPYING.  If not, see <http://www.gnu.org/licenses/>
+ */
+
+/**
+ *
+ * @author Sebastian Javier Marchano (sebasjm)
+ */
+
+import { useTranslationContext } from "@gnu-taler/web-util/browser";
+import { Fragment, h, VNode } from "preact";
+import { useState } from "preact/hooks";
+import { NotificationCard } from "../../../../components/menu/index.js";
+import { MerchantBackend } from "../../../../declaration.js";
+import { useProductAPI } from "../../../../hooks/product.js";
+import { Notification } from "../../../../utils/types.js";
+import { CreatePage } from "./CreatePage.js";
+
+export type Entity = MerchantBackend.Products.ProductAddDetail;
+interface Props {
+  onBack?: () => void;
+  onConfirm: () => void;
+}
+export default function CreateProduct({ onConfirm, onBack }: Props): VNode {
+  const { createProduct } = useProductAPI();
+  const [notif, setNotif] = useState<Notification | undefined>(undefined);
+  const { i18n } = useTranslationContext();
+
+  return (
+    <Fragment>
+      <NotificationCard notification={notif} />
+      <CreatePage
+        onBack={onBack}
+        onCreate={(request: MerchantBackend.Products.ProductAddDetail) => {
+          return createProduct(request)
+            .then(() => onConfirm())
+            .catch((error) => {
+              setNotif({
+                message: i18n.str`could not create product`,
+                type: "ERROR",
+                description: error.message,
+              });
+            });
+        }}
+      />
+    </Fragment>
+  );
+}
diff --git 
a/packages/auditor-backoffice-ui/src/paths/instance/products/list/List.stories.tsx
 
b/packages/auditor-backoffice-ui/src/paths/instance/products/list/List.stories.tsx
new file mode 100644
index 000000000..c2c4d548c
--- /dev/null
+++ 
b/packages/auditor-backoffice-ui/src/paths/instance/products/list/List.stories.tsx
@@ -0,0 +1,61 @@
+/*
+ This file is part of GNU Taler
+ (C) 2021-2023 Taler Systems S.A.
+
+ GNU Taler is free software; you can redistribute it and/or modify it under the
+ terms of the GNU General Public License as published by the Free Software
+ Foundation; either version 3, or (at your option) any later version.
+
+ GNU Taler is distributed in the hope that it will be useful, but WITHOUT ANY
+ WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
+ A PARTICULAR PURPOSE.  See the GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License along with
+ GNU Taler; see the file COPYING.  If not, see <http://www.gnu.org/licenses/>
+ */
+
+/**
+ *
+ * @author Sebastian Javier Marchano (sebasjm)
+ */
+
+import { h, VNode, FunctionalComponent } from "preact";
+import { CardTable as TestedComponent } from "./Table.js";
+
+export default {
+  title: "Pages/Product/List",
+  component: TestedComponent,
+  argTypes: {
+    onCreate: { action: "onCreate" },
+    onSelect: { action: "onSelect" },
+    onDelete: { action: "onDelete" },
+    onUpdate: { action: "onUpdate" },
+  },
+};
+
+function createExample<Props>(
+  Component: FunctionalComponent<Props>,
+  props: Partial<Props>,
+) {
+  const r = (args: any) => <Component {...args} />;
+  r.args = props;
+  return r;
+}
+
+export const Example = createExample(TestedComponent, {
+  instances: [
+    {
+      id: "orderid",
+      description: "description1",
+      description_i18n: {} as any,
+      image: "",
+      price: "TESTKUDOS:10",
+      taxes: [],
+      total_lost: 10,
+      total_sold: 5,
+      total_stock: 15,
+      unit: "bar",
+      address: {},
+    },
+  ],
+});
diff --git 
a/packages/auditor-backoffice-ui/src/paths/instance/products/list/Table.tsx 
b/packages/auditor-backoffice-ui/src/paths/instance/products/list/Table.tsx
new file mode 100644
index 000000000..275f855cb
--- /dev/null
+++ b/packages/auditor-backoffice-ui/src/paths/instance/products/list/Table.tsx
@@ -0,0 +1,496 @@
+/*
+ This file is part of GNU Taler
+ (C) 2021-2023 Taler Systems S.A.
+
+ GNU Taler is free software; you can redistribute it and/or modify it under the
+ terms of the GNU General Public License as published by the Free Software
+ Foundation; either version 3, or (at your option) any later version.
+
+ GNU Taler is distributed in the hope that it will be useful, but WITHOUT ANY
+ WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
+ A PARTICULAR PURPOSE.  See the GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License along with
+ GNU Taler; see the file COPYING.  If not, see <http://www.gnu.org/licenses/>
+ */
+
+/**
+ *
+ * @author Sebastian Javier Marchano (sebasjm)
+ */
+
+import { Amounts } from "@gnu-taler/taler-util";
+import { useTranslationContext } from "@gnu-taler/web-util/browser";
+import { format } from "date-fns";
+import { ComponentChildren, Fragment, h, VNode } from "preact";
+import { StateUpdater, useState } from "preact/hooks";
+import emptyImage from "../../../../assets/empty.png";
+import {
+  FormErrors,
+  FormProvider,
+} from "../../../../components/form/FormProvider.js";
+import { InputCurrency } from "../../../../components/form/InputCurrency.js";
+import { InputNumber } from "../../../../components/form/InputNumber.js";
+import { MerchantBackend, WithId } from "../../../../declaration.js";
+import { dateFormatForSettings, useSettings } from 
"../../../../hooks/useSettings.js";
+
+type Entity = MerchantBackend.Products.ProductDetail & WithId;
+
+interface Props {
+  instances: Entity[];
+  onDelete: (id: Entity) => void;
+  onSelect: (product: Entity) => void;
+  onUpdate: (
+    id: string,
+    data: MerchantBackend.Products.ProductPatchDetail,
+  ) => Promise<void>;
+  onCreate: () => void;
+  selected?: boolean;
+}
+
+export function CardTable({
+  instances,
+  onCreate,
+  onSelect,
+  onUpdate,
+  onDelete,
+}: Props): VNode {
+  const [rowSelection, rowSelectionHandler] = useState<string | undefined>(
+    undefined,
+  );
+  const { i18n } = useTranslationContext();
+  return (
+    <div class="card has-table">
+      <header class="card-header">
+        <p class="card-header-title">
+          <span class="icon">
+            <i class="mdi mdi-shopping" />
+          </span>
+          <i18n.Translate>Inventory</i18n.Translate>
+        </p>
+        <div class="card-header-icon" aria-label="more options">
+          <span
+            class="has-tooltip-left"
+            data-tooltip={i18n.str`add product to inventory`}
+          >
+            <button class="button is-info" type="button" onClick={onCreate}>
+              <span class="icon is-small">
+                <i class="mdi mdi-plus mdi-36px" />
+              </span>
+            </button>
+          </span>
+        </div>
+      </header>
+      <div class="card-content">
+        <div class="b-table has-pagination">
+          <div class="table-wrapper has-mobile-cards">
+            {instances.length > 0 ? (
+              <Table
+                instances={instances}
+                onSelect={onSelect}
+                onDelete={onDelete}
+                onUpdate={onUpdate}
+                rowSelection={rowSelection}
+                rowSelectionHandler={rowSelectionHandler}
+              />
+            ) : (
+              <EmptyTable />
+            )}
+          </div>
+        </div>
+      </div>
+    </div>
+  );
+}
+interface TableProps {
+  rowSelection: string | undefined;
+  instances: Entity[];
+  onSelect: (id: Entity) => void;
+  onUpdate: (
+    id: string,
+    data: MerchantBackend.Products.ProductPatchDetail,
+  ) => Promise<void>;
+  onDelete: (id: Entity) => void;
+  rowSelectionHandler: StateUpdater<string | undefined>;
+}
+
+function Table({
+  rowSelection,
+  rowSelectionHandler,
+  instances,
+  onSelect,
+  onUpdate,
+  onDelete,
+}: TableProps): VNode {
+  const { i18n } = useTranslationContext();
+  const [settings] = useSettings();
+  return (
+    <div class="table-container">
+      <table class="table is-fullwidth is-striped is-hoverable is-fullwidth">
+        <thead>
+          <tr>
+            <th>
+              <i18n.Translate>Image</i18n.Translate>
+            </th>
+            <th>
+              <i18n.Translate>Description</i18n.Translate>
+            </th>
+            <th>
+              <i18n.Translate>Price per unit</i18n.Translate>
+            </th>
+            <th>
+              <i18n.Translate>Taxes</i18n.Translate>
+            </th>
+            <th>
+              <i18n.Translate>Sales</i18n.Translate>
+            </th>
+            <th>
+              <i18n.Translate>Stock</i18n.Translate>
+            </th>
+            <th>
+              <i18n.Translate>Sold</i18n.Translate>
+            </th>
+            <th />
+          </tr>
+        </thead>
+        <tbody>
+          {instances.map((i) => {
+            const restStockInfo = !i.next_restock
+              ? ""
+              : i.next_restock.t_s === "never"
+                ? "never"
+                : `restock at ${format(
+                  new Date(i.next_restock.t_s * 1000),
+                  dateFormatForSettings(settings),
+                )}`;
+            let stockInfo: ComponentChildren = "";
+            if (i.total_stock < 0) {
+              stockInfo = "infinite";
+            } else {
+              const totalStock = i.total_stock - i.total_lost - i.total_sold;
+              stockInfo = (
+                <label title={restStockInfo}>
+                  {totalStock} {i.unit}
+                </label>
+              );
+            }
+
+            const isFree = Amounts.isZero(Amounts.parseOrThrow(i.price));
+
+            return (
+              <Fragment key={i.id}>
+                <tr key="info">
+                  <td
+                    onClick={() =>
+                      rowSelection !== i.id && rowSelectionHandler(i.id)
+                    }
+                    style={{ cursor: "pointer" }}
+                  >
+                    <img
+                      src={i.image ? i.image : emptyImage}
+                      style={{
+                        border: "solid black 1px",
+                        maxHeight: "2em",
+                        width: "auto",
+                        height: "auto",
+                      }}
+                    />
+                  </td>
+                  <td
+                    class="has-tooltip-right"                    
+                    data-tooltip={i.description}
+                    onClick={() =>
+                      rowSelection !== i.id && rowSelectionHandler(i.id)
+                    }
+                    style={{ cursor: "pointer" }}
+                  >
+                    {i.description.length > 30  ? i.description.substring(0, 
30) + "..." : i.description}
+                  </td>
+                  <td
+                    onClick={() =>
+                      rowSelection !== i.id && rowSelectionHandler(i.id)
+                    }
+                    style={{ cursor: "pointer" }}
+                  >
+                    {isFree ? i18n.str`free` : `${i.price} / ${i.unit}`}
+                  </td>
+                  <td
+                    onClick={() =>
+                      rowSelection !== i.id && rowSelectionHandler(i.id)
+                    }
+                    style={{ cursor: "pointer" }}
+                  >
+                    {sum(i.taxes)}
+                  </td>
+                  <td
+                    onClick={() =>
+                      rowSelection !== i.id && rowSelectionHandler(i.id)
+                    }
+                    style={{ cursor: "pointer" }}
+                  >
+                    {difference(i.price, sum(i.taxes))}
+                  </td>
+                  <td
+                    onClick={() =>
+                      rowSelection !== i.id && rowSelectionHandler(i.id)
+                    }
+                    style={{ cursor: "pointer" }}
+                  >
+                    {stockInfo}
+                  </td>
+                  <td
+                    onClick={() =>
+                      rowSelection !== i.id && rowSelectionHandler(i.id)
+                    }
+                    style={{ cursor: "pointer" }}
+                  >
+                    <span style={{"whiteSpace":"nowrap"}}>
+
+                    {i.total_sold} {i.unit}
+                    </span>
+                  </td>
+                  <td class="is-actions-cell right-sticky">
+                    <div class="buttons is-right">
+                      <span
+                        class="has-tooltip-bottom"
+                        data-tooltip={i18n.str`go to product update page`}
+                      >
+                        <button
+                          class="button is-small is-success "
+                          type="button"
+                          onClick={(): void => onSelect(i)}
+                        >
+                          <i18n.Translate>Update</i18n.Translate>
+                        </button>
+                      </span>
+                      <span
+                        class="has-tooltip-left"
+                        data-tooltip={i18n.str`remove this product from the 
database`}
+                      >
+                        <button
+                          class="button is-small is-danger"
+                          type="button"
+                          onClick={(): void => onDelete(i)}
+                        >
+                          <i18n.Translate>Delete</i18n.Translate>
+                        </button>
+                      </span>
+                    </div>
+                  </td>
+                </tr>
+                {rowSelection === i.id && (
+                  <tr key="form">
+                    <td colSpan={10}>
+                      <FastProductUpdateForm
+                        product={i}
+                        onUpdate={(prod) =>
+                          onUpdate(i.id, prod).then((r) =>
+                            rowSelectionHandler(undefined),
+                          )
+                        }
+                        onCancel={() => rowSelectionHandler(undefined)}
+                      />
+                    </td>
+                  </tr>
+                )}
+              </Fragment>
+            );
+          })}
+        </tbody>
+      </table>
+    </div>
+  );
+}
+
+interface FastProductUpdateFormProps {
+  product: Entity;
+  onUpdate: (
+    data: MerchantBackend.Products.ProductPatchDetail,
+  ) => Promise<void>;
+  onCancel: () => void;
+}
+interface FastProductUpdate {
+  incoming: number;
+  lost: number;
+  price: string;
+}
+interface UpdatePrice {
+  price: string;
+}
+
+function FastProductWithInfiniteStockUpdateForm({
+  product,
+  onUpdate,
+  onCancel,
+}: FastProductUpdateFormProps) {
+  const [value, valueHandler] = useState<UpdatePrice>({ price: product.price 
});
+  const { i18n } = useTranslationContext();
+
+  return (
+    <Fragment>
+      <FormProvider<FastProductUpdate>
+        name="added"
+        object={value}
+        valueHandler={valueHandler as any}
+      >
+        <InputCurrency<FastProductUpdate>
+          name="price"
+          label={i18n.str`Price`}
+          tooltip={i18n.str`update the product with new price`}
+        />
+      </FormProvider>
+
+      <div class="buttons is-expanded">
+
+        <div class="buttons mt-5">
+
+          <button class="button mt-5" onClick={onCancel}>
+            <i18n.Translate>Clone</i18n.Translate>
+          </button>
+        </div>
+        <div class="buttons is-right mt-5">
+          <button class="button" onClick={onCancel}>
+            <i18n.Translate>Cancel</i18n.Translate>
+          </button>
+          <span
+            class="has-tooltip-left"
+            data-tooltip={i18n.str`update product with new price`}
+          >
+            <button
+              class="button is-info"
+              onClick={() =>
+                onUpdate({
+                  ...product,
+                  price: value.price,
+                })
+              }
+            >
+              <i18n.Translate>Confirm update</i18n.Translate>
+            </button>
+          </span>
+        </div>
+      </div>
+    </Fragment>
+  );
+}
+
+function FastProductWithManagedStockUpdateForm({
+  product,
+  onUpdate,
+  onCancel,
+}: FastProductUpdateFormProps) {
+  const [value, valueHandler] = useState<FastProductUpdate>({
+    incoming: 0,
+    lost: 0,
+    price: product.price,
+  });
+
+  const currentStock =
+    product.total_stock - product.total_sold - product.total_lost;
+
+  const errors: FormErrors<FastProductUpdate> = {
+    lost:
+      currentStock + value.incoming < value.lost
+        ? `lost cannot be greater that current + incoming (max ${currentStock 
+ value.incoming
+        })`
+        : undefined,
+  };
+
+  const hasErrors = Object.keys(errors).some(
+    (k) => (errors as any)[k] !== undefined,
+  );
+  const { i18n } = useTranslationContext();
+
+  return (
+    <Fragment>
+      <FormProvider<FastProductUpdate>
+        name="added"
+        errors={errors}
+        object={value}
+        valueHandler={valueHandler as any}
+      >
+        <InputNumber<FastProductUpdate>
+          name="incoming"
+          label={i18n.str`Incoming`}
+          tooltip={i18n.str`add more elements to the inventory`}
+        />
+        <InputNumber<FastProductUpdate>
+          name="lost"
+          label={i18n.str`Lost`}
+          tooltip={i18n.str`report elements lost in the inventory`}
+        />
+        <InputCurrency<FastProductUpdate>
+          name="price"
+          label={i18n.str`Price`}
+          tooltip={i18n.str`new price for the product`}
+        />
+      </FormProvider>
+
+      <div class="buttons is-right mt-5">
+        <button class="button" onClick={onCancel}>
+          <i18n.Translate>Cancel</i18n.Translate>
+        </button>
+        <span
+          class="has-tooltip-left"
+          data-tooltip={
+            hasErrors
+              ? i18n.str`the are value with errors`
+              : i18n.str`update product with new stock and price`
+          }
+        >
+          <button
+            class="button is-info"
+            disabled={hasErrors}
+            onClick={() =>
+              onUpdate({
+                ...product,
+                total_stock: product.total_stock + value.incoming,
+                total_lost: product.total_lost + value.lost,
+                price: value.price,
+              })
+            }
+          >
+            <i18n.Translate>Confirm</i18n.Translate>
+          </button>
+        </span>
+      </div>
+    </Fragment>
+  );
+}
+
+function FastProductUpdateForm(props: FastProductUpdateFormProps) {
+  return props.product.total_stock === -1 ? (
+    <FastProductWithInfiniteStockUpdateForm {...props} />
+  ) : (
+    <FastProductWithManagedStockUpdateForm {...props} />
+  );
+}
+
+function EmptyTable(): VNode {
+  const { i18n } = useTranslationContext();
+  return (
+    <div class="content has-text-grey has-text-centered">
+      <p>
+        <span class="icon is-large">
+          <i class="mdi mdi-emoticon-sad mdi-48px" />
+        </span>
+      </p>
+      <p>
+        <i18n.Translate>
+          There is no products yet, add more pressing the + sign
+        </i18n.Translate>
+      </p>
+    </div>
+  );
+}
+
+function difference(price: string, tax: number) {
+  if (!tax) return price;
+  const ps = price.split(":");
+  const p = parseInt(ps[1], 10);
+  ps[1] = `${p - tax}`;
+  return ps.join(":");
+}
+function sum(taxes: MerchantBackend.Tax[]) {
+  return taxes.reduce((p, c) => p + parseInt(c.tax.split(":")[1], 10), 0);
+}
diff --git 
a/packages/auditor-backoffice-ui/src/paths/instance/products/list/index.tsx 
b/packages/auditor-backoffice-ui/src/paths/instance/products/list/index.tsx
new file mode 100644
index 000000000..942b5d0ac
--- /dev/null
+++ b/packages/auditor-backoffice-ui/src/paths/instance/products/list/index.tsx
@@ -0,0 +1,150 @@
+/*
+ This file is part of GNU Taler
+ (C) 2021-2023 Taler Systems S.A.
+
+ GNU Taler is free software; you can redistribute it and/or modify it under the
+ terms of the GNU General Public License as published by the Free Software
+ Foundation; either version 3, or (at your option) any later version.
+
+ GNU Taler is distributed in the hope that it will be useful, but WITHOUT ANY
+ WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
+ A PARTICULAR PURPOSE.  See the GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License along with
+ GNU Taler; see the file COPYING.  If not, see <http://www.gnu.org/licenses/>
+ */
+
+/**
+ *
+ * @author Sebastian Javier Marchano (sebasjm)
+ */
+
+import {
+  ErrorType,
+  HttpError,
+  useTranslationContext,
+} from "@gnu-taler/web-util/browser";
+import { h, VNode } from "preact";
+import { useState } from "preact/hooks";
+import { Loading } from "../../../../components/exception/loading.js";
+import { NotificationCard } from "../../../../components/menu/index.js";
+import { MerchantBackend, WithId } from "../../../../declaration.js";
+import {
+  useInstanceProducts,
+  useProductAPI,
+} from "../../../../hooks/product.js";
+import { Notification } from "../../../../utils/types.js";
+import { CardTable } from "./Table.js";
+import { HttpStatusCode } from "@gnu-taler/taler-util";
+import { ConfirmModal, DeleteModal } from 
"../../../../components/modal/index.js";
+import { JumpToElementById } from 
"../../../../components/form/JumpToElementById.js";
+
+interface Props {
+  onUnauthorized: () => VNode;
+  onNotFound: () => VNode;
+  onCreate: () => void;
+  onSelect: (id: string) => void;
+  onLoadError: (e: HttpError<MerchantBackend.ErrorDetail>) => VNode;
+}
+export default function ProductList({
+  onUnauthorized,
+  onLoadError,
+  onCreate,
+  onSelect,
+  onNotFound,
+}: Props): VNode {
+  const result = useInstanceProducts();
+  const { deleteProduct, updateProduct, getProduct } = useProductAPI();
+  const [deleting, setDeleting] =
+    useState<MerchantBackend.Products.ProductDetail & WithId | null>(null);
+  const [notif, setNotif] = useState<Notification | undefined>(undefined);
+
+  const { i18n } = useTranslationContext();
+
+  if (result.loading) return <Loading />;
+  if (!result.ok) {
+    if (
+      result.type === ErrorType.CLIENT &&
+      result.status === HttpStatusCode.Unauthorized
+    )
+      return onUnauthorized();
+    if (
+      result.type === ErrorType.CLIENT &&
+      result.status === HttpStatusCode.NotFound
+    )
+      return onNotFound();
+    return onLoadError(result);
+  }
+
+  return (
+    <section class="section is-main-section">
+      <NotificationCard notification={notif} />
+
+      <JumpToElementById
+        testIfExist={getProduct} 
+        onSelect={onSelect}
+        description={i18n.str`jump to product with the given product ID`}
+        palceholder={i18n.str`product id`}
+      />
+
+      <CardTable
+        instances={result.data}
+        onCreate={onCreate}
+        onUpdate={(id, prod) =>
+          updateProduct(id, prod)
+            .then(() =>
+              setNotif({
+                message: i18n.str`product updated successfully`,
+                type: "SUCCESS",
+              }),
+            )
+            .catch((error) =>
+              setNotif({
+                message: i18n.str`could not update the product`,
+                type: "ERROR",
+                description: error.message,
+              }),
+            )
+        }
+        onSelect={(product) => onSelect(product.id)}
+        onDelete={(prod: MerchantBackend.Products.ProductDetail & WithId) =>
+          setDeleting(prod)
+        }
+      />
+
+      {deleting && (
+        <ConfirmModal
+          label={`Delete product`}
+          description={`Delete the product "${deleting.description}"`}
+          danger
+          active
+          onCancel={() => setDeleting(null)}
+          onConfirm={async (): Promise<void> => {
+            try {
+              await deleteProduct(deleting.id);
+              setNotif({
+                message: i18n.str`Product "${deleting.description}" (ID: 
${deleting.id}) has been deleted`,
+                type: "SUCCESS",
+              });
+            } catch (error) {
+              setNotif({
+                message: i18n.str`Failed to delete product`,
+                type: "ERROR",
+                description: error instanceof Error ? error.message : 
undefined,
+              });
+            }
+            setDeleting(null);
+          }}
+        >
+          <p>
+            If you delete the product named 
<b>&quot;{deleting.description}&quot;</b> (ID:{" "}
+            <b>{deleting.id}</b>), the stock and related information will be 
lost
+          </p>
+          <p class="warning">
+            Deleting an product <b>cannot be undone</b>.
+          </p>
+        </ConfirmModal>
+      )}
+    </section>
+  );
+}
diff --git 
a/packages/auditor-backoffice-ui/src/paths/instance/products/update/Update.stories.tsx
 
b/packages/auditor-backoffice-ui/src/paths/instance/products/update/Update.stories.tsx
new file mode 100644
index 000000000..a85b13b8b
--- /dev/null
+++ 
b/packages/auditor-backoffice-ui/src/paths/instance/products/update/Update.stories.tsx
@@ -0,0 +1,73 @@
+/*
+ This file is part of GNU Taler
+ (C) 2021-2023 Taler Systems S.A.
+
+ GNU Taler is free software; you can redistribute it and/or modify it under the
+ terms of the GNU General Public License as published by the Free Software
+ Foundation; either version 3, or (at your option) any later version.
+
+ GNU Taler is distributed in the hope that it will be useful, but WITHOUT ANY
+ WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
+ A PARTICULAR PURPOSE.  See the GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License along with
+ GNU Taler; see the file COPYING.  If not, see <http://www.gnu.org/licenses/>
+ */
+
+/**
+ *
+ * @author Sebastian Javier Marchano (sebasjm)
+ */
+
+import { h, VNode, FunctionalComponent } from "preact";
+import { UpdatePage as TestedComponent } from "./UpdatePage.js";
+
+export default {
+  title: "Pages/Product/Update",
+  component: TestedComponent,
+  argTypes: {
+    onUpdate: { action: "onUpdate" },
+    onBack: { action: "onBack" },
+  },
+};
+
+function createExample<Props>(
+  Component: FunctionalComponent<Props>,
+  props: Partial<Props>,
+) {
+  const r = (args: any) => <Component {...args} />;
+  r.args = props;
+  return r;
+}
+
+export const WithManagedStock = createExample(TestedComponent, {
+  product: {
+    product_id: "20102-ASDAS-QWE",
+    description: "description1",
+    description_i18n: {} as any,
+    image: "",
+    price: "TESTKUDOS:10",
+    taxes: [],
+    total_lost: 10,
+    total_sold: 5,
+    total_stock: 15,
+    unit: "bar",
+    address: {},
+  },
+});
+
+export const WithInfiniteStock = createExample(TestedComponent, {
+  product: {
+    product_id: "20102-ASDAS-QWE",
+    description: "description1",
+    description_i18n: {} as any,
+    image: "",
+    price: "TESTKUDOS:10",
+    taxes: [],
+    total_lost: 10,
+    total_sold: 5,
+    total_stock: -1,
+    unit: "bar",
+    address: {},
+  },
+});
diff --git 
a/packages/auditor-backoffice-ui/src/paths/instance/products/update/UpdatePage.tsx
 
b/packages/auditor-backoffice-ui/src/paths/instance/products/update/UpdatePage.tsx
new file mode 100644
index 000000000..97715171e
--- /dev/null
+++ 
b/packages/auditor-backoffice-ui/src/paths/instance/products/update/UpdatePage.tsx
@@ -0,0 +1,99 @@
+/*
+ This file is part of GNU Taler
+ (C) 2021-2023 Taler Systems S.A.
+
+ GNU Taler is free software; you can redistribute it and/or modify it under the
+ terms of the GNU General Public License as published by the Free Software
+ Foundation; either version 3, or (at your option) any later version.
+
+ GNU Taler is distributed in the hope that it will be useful, but WITHOUT ANY
+ WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
+ A PARTICULAR PURPOSE.  See the GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License along with
+ GNU Taler; see the file COPYING.  If not, see <http://www.gnu.org/licenses/>
+ */
+
+/**
+ *
+ * @author Sebastian Javier Marchano (sebasjm)
+ */
+
+import { useTranslationContext } from "@gnu-taler/web-util/browser";
+import { h, VNode } from "preact";
+import { AsyncButton } from "../../../../components/exception/AsyncButton.js";
+import { ProductForm } from "../../../../components/product/ProductForm.js";
+import { MerchantBackend } from "../../../../declaration.js";
+import { useListener } from "../../../../hooks/listener.js";
+
+type Entity = MerchantBackend.Products.ProductDetail & { product_id: string };
+
+interface Props {
+  onUpdate: (d: Entity) => Promise<void>;
+  onBack?: () => void;
+  product: Entity;
+}
+
+export function UpdatePage({ product, onUpdate, onBack }: Props): VNode {
+  const [submitForm, addFormSubmitter] = useListener<Entity | undefined>(
+    (result) => {
+      if (result) return onUpdate(result);
+      return Promise.resolve();
+    },
+  );
+
+  const { i18n } = useTranslationContext();
+
+  return (
+    <div>
+      <section class="section">
+        <section class="hero is-hero-bar">
+          <div class="hero-body">
+            <div class="level">
+              <div class="level-left">
+                <div class="level-item">
+                  <span class="is-size-4">
+                    <i18n.Translate>Product id:</i18n.Translate>
+                    <b>{product.product_id}</b>
+                  </span>
+                </div>
+              </div>
+            </div>
+          </div>
+        </section>
+        <hr />
+
+        <div class="columns">
+          <div class="column" />
+          <div class="column is-four-fifths">
+            <ProductForm
+              initial={product}
+              onSubscribe={addFormSubmitter}
+              alreadyExist
+            />
+
+            <div class="buttons is-right mt-5">
+              {onBack && (
+                <button class="button" onClick={onBack}>
+                  <i18n.Translate>Cancel</i18n.Translate>
+                </button>
+              )}
+              <AsyncButton
+                onClick={submitForm}
+                data-tooltip={
+                  !submitForm
+                    ? i18n.str`Need to complete marked fields`
+                    : "confirm operation"
+                }
+                disabled={!submitForm}
+              >
+                <i18n.Translate>Confirm</i18n.Translate>
+              </AsyncButton>
+            </div>
+          </div>
+          <div class="column" />
+        </div>
+      </section>
+    </div>
+  );
+}
diff --git 
a/packages/auditor-backoffice-ui/src/paths/instance/products/update/index.tsx 
b/packages/auditor-backoffice-ui/src/paths/instance/products/update/index.tsx
new file mode 100644
index 000000000..8e0f7647f
--- /dev/null
+++ 
b/packages/auditor-backoffice-ui/src/paths/instance/products/update/index.tsx
@@ -0,0 +1,95 @@
+/*
+ This file is part of GNU Taler
+ (C) 2021-2023 Taler Systems S.A.
+
+ GNU Taler is free software; you can redistribute it and/or modify it under the
+ terms of the GNU General Public License as published by the Free Software
+ Foundation; either version 3, or (at your option) any later version.
+
+ GNU Taler is distributed in the hope that it will be useful, but WITHOUT ANY
+ WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
+ A PARTICULAR PURPOSE.  See the GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License along with
+ GNU Taler; see the file COPYING.  If not, see <http://www.gnu.org/licenses/>
+ */
+
+/**
+ *
+ * @author Sebastian Javier Marchano (sebasjm)
+ */
+
+import {
+  ErrorType,
+  HttpError,
+  useTranslationContext,
+} from "@gnu-taler/web-util/browser";
+import { Fragment, h, VNode } from "preact";
+import { useState } from "preact/hooks";
+import { Loading } from "../../../../components/exception/loading.js";
+import { NotificationCard } from "../../../../components/menu/index.js";
+import { MerchantBackend } from "../../../../declaration.js";
+import { useProductAPI, useProductDetails } from 
"../../../../hooks/product.js";
+import { Notification } from "../../../../utils/types.js";
+import { UpdatePage } from "./UpdatePage.js";
+import { HttpStatusCode } from "@gnu-taler/taler-util";
+
+export type Entity = MerchantBackend.Products.ProductAddDetail;
+interface Props {
+  onBack?: () => void;
+  onConfirm: () => void;
+  onUnauthorized: () => VNode;
+  onNotFound: () => VNode;
+  onLoadError: (e: HttpError<MerchantBackend.ErrorDetail>) => VNode;
+  pid: string;
+}
+export default function UpdateProduct({
+  pid,
+  onConfirm,
+  onBack,
+  onUnauthorized,
+  onNotFound,
+  onLoadError,
+}: Props): VNode {
+  const { updateProduct } = useProductAPI();
+  const result = useProductDetails(pid);
+  const [notif, setNotif] = useState<Notification | undefined>(undefined);
+
+  const { i18n } = useTranslationContext();
+
+  if (result.loading) return <Loading />;
+  if (!result.ok) {
+    if (
+      result.type === ErrorType.CLIENT &&
+      result.status === HttpStatusCode.Unauthorized
+    )
+      return onUnauthorized();
+    if (
+      result.type === ErrorType.CLIENT &&
+      result.status === HttpStatusCode.NotFound
+    )
+      return onNotFound();
+    return onLoadError(result);
+  }
+
+  return (
+    <Fragment>
+      <NotificationCard notification={notif} />
+      <UpdatePage
+        product={{ ...result.data, product_id: pid }}
+        onBack={onBack}
+        onUpdate={(data) => {
+          return updateProduct(pid, data)
+            .then(onConfirm)
+            .catch((error) => {
+              setNotif({
+                message: i18n.str`could not create product`,
+                type: "ERROR",
+                description: error.message,
+              });
+            });
+        }}
+      />
+    </Fragment>
+  );
+}
diff --git 
a/packages/auditor-backoffice-ui/src/paths/instance/reserves/create/Create.stories.tsx
 
b/packages/auditor-backoffice-ui/src/paths/instance/reserves/create/Create.stories.tsx
new file mode 100644
index 000000000..5542c028a
--- /dev/null
+++ 
b/packages/auditor-backoffice-ui/src/paths/instance/reserves/create/Create.stories.tsx
@@ -0,0 +1,43 @@
+/*
+ This file is part of GNU Taler
+ (C) 2021-2023 Taler Systems S.A.
+
+ GNU Taler is free software; you can redistribute it and/or modify it under the
+ terms of the GNU General Public License as published by the Free Software
+ Foundation; either version 3, or (at your option) any later version.
+
+ GNU Taler is distributed in the hope that it will be useful, but WITHOUT ANY
+ WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
+ A PARTICULAR PURPOSE.  See the GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License along with
+ GNU Taler; see the file COPYING.  If not, see <http://www.gnu.org/licenses/>
+ */
+
+/**
+ *
+ * @author Sebastian Javier Marchano (sebasjm)
+ */
+
+import { h, VNode, FunctionalComponent } from "preact";
+import { CreatePage as TestedComponent } from "./CreatePage.js";
+
+export default {
+  title: "Pages/Reserve/Create",
+  component: TestedComponent,
+  argTypes: {
+    onCreate: { action: "onCreate" },
+    onBack: { action: "onBack" },
+  },
+};
+
+function createExample<Props>(
+  Component: FunctionalComponent<Props>,
+  props: Partial<Props>,
+) {
+  const r = (args: any) => <Component {...args} />;
+  r.args = props;
+  return r;
+}
+
+export const Example = createExample(TestedComponent, {});
diff --git 
a/packages/auditor-backoffice-ui/src/paths/instance/reserves/create/CreatePage.tsx
 
b/packages/auditor-backoffice-ui/src/paths/instance/reserves/create/CreatePage.tsx
new file mode 100644
index 000000000..e46941b6d
--- /dev/null
+++ 
b/packages/auditor-backoffice-ui/src/paths/instance/reserves/create/CreatePage.tsx
@@ -0,0 +1,277 @@
+/*
+ This file is part of GNU Taler
+ (C) 2021-2023 Taler Systems S.A.
+
+ GNU Taler is free software; you can redistribute it and/or modify it under the
+ terms of the GNU General Public License as published by the Free Software
+ Foundation; either version 3, or (at your option) any later version.
+
+ GNU Taler is distributed in the hope that it will be useful, but WITHOUT ANY
+ WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
+ A PARTICULAR PURPOSE.  See the GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License along with
+ GNU Taler; see the file COPYING.  If not, see <http://www.gnu.org/licenses/>
+ */
+
+/**
+ *
+ * @author Sebastian Javier Marchano (sebasjm)
+ */
+
+import { HttpError, RequestError, useApiContext, useTranslationContext } from 
"@gnu-taler/web-util/browser";
+import { Fragment, h, VNode } from "preact";
+import { StateUpdater, useEffect, useState } from "preact/hooks";
+import { AsyncButton } from "../../../../components/exception/AsyncButton.js";
+import {
+  FormErrors,
+  FormProvider,
+} from "../../../../components/form/FormProvider.js";
+import { Input } from "../../../../components/form/Input.js";
+import { InputCurrency } from "../../../../components/form/InputCurrency.js";
+import { InputSelector } from "../../../../components/form/InputSelector.js";
+import { MerchantBackend } from "../../../../declaration.js";
+import {
+  PAYTO_WIRE_METHOD_LOOKUP,
+  URL_REGEX,
+} from "../../../../utils/constants.js";
+import { useBackendBaseRequest } from "../../../../hooks/backend.js";
+import { parsePaytoUri } from "@gnu-taler/taler-util";
+
+type Entity = MerchantBackend.Rewards.ReserveCreateRequest;
+
+interface Props {
+  onCreate: (d: Entity) => Promise<void>;
+  onBack?: () => void;
+}
+
+enum Steps {
+  EXCHANGE,
+  WIRE_METHOD,
+}
+
+interface ViewProps {
+  step: Steps;
+  setCurrentStep: (s: Steps) => void;
+  reserve: Partial<Entity>;
+  onBack?: () => void;
+  submitForm: () => Promise<void>;
+  setReserve: StateUpdater<Partial<Entity>>;
+}
+function ViewStep({
+  step,
+  setCurrentStep,
+  reserve,
+  onBack,
+  submitForm,
+  setReserve,
+}: ViewProps): VNode {
+  const { i18n } = useTranslationContext();
+  const {request} = useApiContext()
+  const [wireMethods, setWireMethods] = useState<Array<string>>([]);
+  const [exchangeQueryError, setExchangeQueryError] = useState<
+    string | undefined
+  >(undefined);
+
+  useEffect(() => {
+    setExchangeQueryError(undefined);
+  }, [reserve.exchange_url]);
+
+  switch (step) {
+    case Steps.EXCHANGE: {
+      const errors: FormErrors<Entity> = {
+        initial_balance: !reserve.initial_balance
+          ? "cannot be empty"
+          : !(parseInt(reserve.initial_balance.split(":")[1], 10) > 0)
+            ? i18n.str`it should be greater than 0`
+            : undefined,
+        exchange_url: !reserve.exchange_url
+          ? i18n.str`cannot be empty`
+          : !URL_REGEX.test(reserve.exchange_url)
+            ? i18n.str`must be a valid URL`
+            : !exchangeQueryError
+              ? undefined
+              : exchangeQueryError,
+      };
+
+      const hasErrors = Object.keys(errors).some(
+        (k) => (errors as any)[k] !== undefined,
+      );
+
+      return (
+        <Fragment>
+          <FormProvider<Entity>
+            object={reserve}
+            errors={errors}
+            valueHandler={setReserve}
+          >
+            <InputCurrency<Entity>
+              name="initial_balance"
+              label={i18n.str`Initial balance`}
+              tooltip={i18n.str`balance prior to deposit`}
+            />
+            <Input<Entity>
+              name="exchange_url"
+              label={i18n.str`Exchange URL`}
+              tooltip={i18n.str`URL of exchange`}
+            />
+          </FormProvider>
+
+          <div class="buttons is-right mt-5">
+            {onBack && (
+              <button class="button" onClick={onBack}>
+                <i18n.Translate>Cancel</i18n.Translate>
+              </button>
+            )}
+            <AsyncButton
+              class="has-tooltip-left"
+              onClick={() => {
+                if (!reserve.exchange_url) {
+                  return Promise.resolve();
+                }
+                
+                return request<any>(reserve.exchange_url, "keys")
+                  .then((r) => {
+                    console.log(r)
+                    if (r.loading) return;
+                    if (r.ok) {
+                      const wireMethods = r.data.accounts.map((a: any) => {
+                        const p = parsePaytoUri(a.payto_uri);
+                        const r = p?.targetType
+                        return r
+                      }).filter((x:any) => !!x);
+                      setWireMethods(Array.from(new Set(wireMethods)));
+                    }
+                    setCurrentStep(Steps.WIRE_METHOD);
+                    return;
+                  })
+                  .catch((r: RequestError<{}>) => {
+                    console.log(r.cause)
+                    setExchangeQueryError(r.cause.message);
+                  });
+              }}
+              data-tooltip={
+                hasErrors
+                  ? i18n.str`Need to complete marked fields`
+                  : "confirm operation"
+              }
+              disabled={hasErrors}
+            >
+              <i18n.Translate>Next</i18n.Translate>
+            </AsyncButton>
+          </div>
+        </Fragment>
+      );
+    }
+
+    case Steps.WIRE_METHOD: {
+      const errors: FormErrors<Entity> = {
+        wire_method: !reserve.wire_method
+          ? i18n.str`cannot be empty`
+          : undefined,
+      };
+
+      const hasErrors = Object.keys(errors).some(
+        (k) => (errors as any)[k] !== undefined,
+      );
+      return (
+        <Fragment>
+          <FormProvider<Entity>
+            object={reserve}
+            errors={errors}
+            valueHandler={setReserve}
+          >
+            <InputCurrency<Entity>
+              name="initial_balance"
+              label={i18n.str`Initial balance`}
+              tooltip={i18n.str`balance prior to deposit`}
+              readonly
+            />
+            <Input<Entity>
+              name="exchange_url"
+              label={i18n.str`Exchange URL`}
+              tooltip={i18n.str`URL of exchange`}
+              readonly
+            />
+            <InputSelector<Entity>
+              name="wire_method"
+              label={i18n.str`Wire method`}
+              tooltip={i18n.str`method to use for wire transfer`}
+              values={wireMethods}
+              placeholder={i18n.str`Select one wire method`}
+            />
+          </FormProvider>
+          <div class="buttons is-right mt-5">
+            {onBack && (
+              <button
+                class="button"
+                onClick={() => setCurrentStep(Steps.EXCHANGE)}
+              >
+                <i18n.Translate>Back</i18n.Translate>
+              </button>
+            )}
+            <AsyncButton
+              onClick={submitForm}
+              data-tooltip={
+                hasErrors
+                  ? i18n.str`Need to complete marked fields`
+                  : "confirm operation"
+              }
+              disabled={hasErrors}
+            >
+              <i18n.Translate>Confirm</i18n.Translate>
+            </AsyncButton>
+          </div>
+        </Fragment>
+      );
+    }
+  }
+}
+
+export function CreatePage({ onCreate, onBack }: Props): VNode {
+  const [reserve, setReserve] = useState<Partial<Entity>>({});
+
+  const submitForm = () => {
+    return onCreate(reserve as Entity);
+  };
+
+  const [currentStep, setCurrentStep] = useState(Steps.EXCHANGE);
+
+  return (
+    <div>
+      <section class="section is-main-section">
+        <div class="columns">
+          <div class="column" />
+          <div class="column is-four-fifths">
+            <div class="tabs is-toggle is-fullwidth is-small">
+              <ul>
+                <li class={currentStep === Steps.EXCHANGE ? "is-active" : ""}>
+                  <a style={{ cursor: "initial" }}>
+                    <span>Step 1: Specify exchange</span>
+                  </a>
+                </li>
+                <li
+                  class={currentStep === Steps.WIRE_METHOD ? "is-active" : ""}
+                >
+                  <a style={{ cursor: "initial" }}>
+                    <span>Step 2: Select wire method</span>
+                  </a>
+                </li>
+              </ul>
+            </div>
+
+            <ViewStep
+              step={currentStep}
+              reserve={reserve}
+              setCurrentStep={setCurrentStep}
+              setReserve={setReserve}
+              submitForm={submitForm}
+              onBack={onBack}
+            />
+          </div>
+          <div class="column" />
+        </div>
+      </section>
+    </div>
+  );
+}
diff --git 
a/packages/auditor-backoffice-ui/src/paths/instance/reserves/create/CreatedSuccessfully.stories.tsx
 
b/packages/auditor-backoffice-ui/src/paths/instance/reserves/create/CreatedSuccessfully.stories.tsx
new file mode 100644
index 000000000..445ca3ef0
--- /dev/null
+++ 
b/packages/auditor-backoffice-ui/src/paths/instance/reserves/create/CreatedSuccessfully.stories.tsx
@@ -0,0 +1,120 @@
+/*
+ This file is part of GNU Taler
+ (C) 2021-2023 Taler Systems S.A.
+
+ GNU Taler is free software; you can redistribute it and/or modify it under the
+ terms of the GNU General Public License as published by the Free Software
+ Foundation; either version 3, or (at your option) any later version.
+
+ GNU Taler is distributed in the hope that it will be useful, but WITHOUT ANY
+ WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
+ A PARTICULAR PURPOSE.  See the GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License along with
+ GNU Taler; see the file COPYING.  If not, see <http://www.gnu.org/licenses/>
+ */
+
+/**
+ *
+ * @author Sebastian Javier Marchano (sebasjm)
+ */
+
+import { h, VNode, FunctionalComponent } from "preact";
+import { CreatedSuccessfully as TestedComponent } from 
"./CreatedSuccessfully.js";
+import * as tests from "@gnu-taler/web-util/testing";
+
+export default {
+  title: "Pages/Reserve/CreatedSuccessfully",
+  component: TestedComponent,
+  argTypes: {
+    onCreate: { action: "onCreate" },
+    onBack: { action: "onBack" },
+  },
+};
+
+export const OneBankAccount = tests.createExample(TestedComponent, {
+  entity: {
+    request: {
+      exchange_url: "http://exchange.taler/";,
+      initial_balance: "TESTKUDOS:1",
+      wire_method: "x-taler-bank",
+    },
+    response: {
+      accounts: [
+        {
+          payto_uri: "payto://x-taler-bank/bank.taler:8080/exchange_account",
+          credit_restrictions: [],
+          debit_restrictions: [],
+          master_sig: "asd",
+          conversion_url: "",
+        },
+      ],
+      reserve_pub: "WEQWDASDQWEASDADASDQWEQWEASDAS",
+    },
+  },
+});
+
+export const ThreeBankAccount = tests.createExample(TestedComponent, {
+  entity: {
+    request: {
+      exchange_url: "http://exchange.taler/";,
+      initial_balance: "TESTKUDOS:1",
+      wire_method: "x-taler-bank",
+    },
+    response: {
+      accounts: [
+        {
+          payto_uri: "payto://x-taler-bank/bank.taler:8080/exchange_account",
+          credit_restrictions: [],
+          debit_restrictions: [],
+          master_sig: "asd",
+          conversion_url: "",
+        },
+        {
+          payto_uri: "payto://x-taler-bank/bank1.taler:8080/asd",
+          credit_restrictions: [],
+          debit_restrictions: [],
+          master_sig: "asd",
+          conversion_url: "",
+        },
+        {
+          payto_uri: "payto://x-taler-bank/bank2.taler:8080/qwe",
+          credit_restrictions: [],
+          debit_restrictions: [],
+          master_sig: "asd",
+          conversion_url: "",
+        },
+      ],
+      reserve_pub: "WEQWDASDQWEASDADASDQWEQWEASDAS",
+    },
+  },
+});
+
+export const NoBankAccount = tests.createExample(TestedComponent, {
+  entity: {
+    request: {
+      exchange_url: "http://exchange.taler/";,
+      initial_balance: "TESTKUDOS:1",
+      wire_method: "x-taler-bank",
+    },
+    response: {
+      accounts: [
+        {
+          payto_uri: "payo://x-talr-bank/bank.taler:8080/exchange_account",
+          credit_restrictions: [],
+          debit_restrictions: [],
+          master_sig: "asd",
+          conversion_url: "",
+        },
+        {
+          payto_uri: "payto://x-taler-bank",
+          credit_restrictions: [],
+          debit_restrictions: [],
+          master_sig: "asd",
+          conversion_url: "",
+        },
+      ],
+      reserve_pub: "WEQWDASDQWEASDADASDQWEQWEASDAS",
+    },
+  },
+});
diff --git 
a/packages/auditor-backoffice-ui/src/paths/instance/reserves/create/CreatedSuccessfully.tsx
 
b/packages/auditor-backoffice-ui/src/paths/instance/reserves/create/CreatedSuccessfully.tsx
new file mode 100644
index 000000000..1d512c843
--- /dev/null
+++ 
b/packages/auditor-backoffice-ui/src/paths/instance/reserves/create/CreatedSuccessfully.tsx
@@ -0,0 +1,190 @@
+/*
+ This file is part of GNU Taler
+ (C) 2021-2023 Taler Systems S.A.
+
+ GNU Taler is free software; you can redistribute it and/or modify it under the
+ terms of the GNU General Public License as published by the Free Software
+ Foundation; either version 3, or (at your option) any later version.
+
+ GNU Taler is distributed in the hope that it will be useful, but WITHOUT ANY
+ WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
+ A PARTICULAR PURPOSE.  See the GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License along with
+ GNU Taler; see the file COPYING.  If not, see <http://www.gnu.org/licenses/>
+ */
+
+import { parsePaytoUri, stringifyPaytoUri } from "@gnu-taler/taler-util";
+import { useTranslationContext } from "@gnu-taler/web-util/browser";
+import { Fragment, VNode, h } from "preact";
+import { QR } from "../../../../components/exception/QR.js";
+import { CreatedSuccessfully as Template } from 
"../../../../components/notifications/CreatedSuccessfully.js";
+import { MerchantBackend, WireAccount } from "../../../../declaration.js";
+
+type Entity = {
+  request: MerchantBackend.Rewards.ReserveCreateRequest;
+  response: MerchantBackend.Rewards.ReserveCreateConfirmation;
+};
+
+interface Props {
+  entity: Entity;
+  onConfirm: () => void;
+  onCreateAnother?: () => void;
+}
+
+function isNotUndefined<X>(x: X | undefined): x is X {
+  return !!x;
+}
+
+export function CreatedSuccessfully({
+  entity,
+  onConfirm,
+  onCreateAnother,
+}: Props): VNode {
+  const { i18n } = useTranslationContext();
+  return (
+    <Template onConfirm={onConfirm} onCreateAnother={onCreateAnother}>
+      <div class="field is-horizontal">
+        <div class="field-label is-normal">
+          <label class="label">Amount</label>
+        </div>
+        <div class="field-body is-flex-grow-3">
+          <div class="field">
+            <p class="control">
+              <input
+                readonly
+                class="input"
+                value={entity.request.initial_balance}
+              />
+            </p>
+          </div>
+        </div>
+      </div>
+      <div class="field is-horizontal">
+        <div class="field-label is-normal">
+          <label class="label">Wire transfer subject</label>
+        </div>
+        <div class="field-body is-flex-grow-3">
+          <div class="field">
+            <p class="control">
+              <input
+                class="input"
+                readonly
+                value={entity.response.reserve_pub}
+              />
+            </p>
+          </div>
+        </div>
+      </div>
+      <ShowAccountsOfReserveAsQRWithLink
+        accounts={entity.response.accounts ?? []}
+        message={entity.response.reserve_pub}
+        amount={entity.request.initial_balance}
+      />
+    </Template>
+  );
+}
+
+export function ShowAccountsOfReserveAsQRWithLink({
+  accounts,
+  message,
+  amount,
+}: {
+  accounts: WireAccount[];
+  message: string;
+  amount: string;
+}): VNode {
+  const { i18n } = useTranslationContext();
+  const accountsInfo = !accounts
+    ? []
+    : accounts
+      .map((acc) => {
+        const p = parsePaytoUri(acc.payto_uri);
+        if (p) {
+          p.params["message"] = message;
+          p.params["amount"] = amount;
+        }
+        return p;
+      })
+      .filter(isNotUndefined);
+
+  const links = accountsInfo.map((a) => stringifyPaytoUri(a));
+
+  if (links.length === 0) {
+    return (
+      <Fragment>
+        <p class="is-size-5">
+          The reserve have invalid accounts. List of invalid payto URIs below:
+        </p>
+        <ul>
+          {accounts.map((a, idx) => {
+            return <li key={idx}>{a.payto_uri}</li>;
+          })}
+        </ul>
+      </Fragment>
+    );
+  }
+
+  if (links.length === 1) {
+    return (
+      <Fragment>
+        <p class="is-size-5">
+          <i18n.Translate>
+            To complete the setup of the reserve, you must now initiate a wire
+            transfer using the given wire transfer subject and crediting the
+            specified amount to the indicated account of the exchange.
+          </i18n.Translate>
+        </p>
+        <p style={{ margin: 10 }}>
+          <b>Exchange bank account</b>
+        </p>
+        <QR text={links[0]} />
+        <p class="is-size-5">
+          <i18n.Translate>
+            If your system supports RFC 8905, you can do this by opening this
+            URI:
+          </i18n.Translate>
+        </p>
+        <pre>
+          <a target="_blank" rel="noreferrer" href={links[0]}>
+            {links[0]}
+          </a>
+        </pre>
+      </Fragment>
+    );
+  }
+
+  return (
+    <div>
+      <p class="is-size-5">
+        <i18n.Translate>
+          To complete the setup of the reserve, you must now initiate a wire
+          transfer using the given wire transfer subject and crediting the
+          specified amount to one of the indicated account of the exchange.
+        </i18n.Translate>
+      </p>
+
+      <p style={{ margin: 10 }}>
+        <b>Exchange bank accounts</b>
+      </p>
+      <p class="is-size-5">
+        <i18n.Translate>
+          If your system supports RFC 8905, you can do this by clicking on the
+          URI below the QR code:
+        </i18n.Translate>
+      </p>
+      {links.map((link) => {
+        return (
+          <Fragment>
+            <QR text={link} />
+            <pre>
+              <a target="_blank" rel="noreferrer" href={link}>
+                {link}
+              </a>
+            </pre>
+          </Fragment>
+        );
+      })}
+    </div>
+  );
+}
diff --git 
a/packages/auditor-backoffice-ui/src/paths/instance/reserves/create/index.tsx 
b/packages/auditor-backoffice-ui/src/paths/instance/reserves/create/index.tsx
new file mode 100644
index 000000000..4bbaf1459
--- /dev/null
+++ 
b/packages/auditor-backoffice-ui/src/paths/instance/reserves/create/index.tsx
@@ -0,0 +1,71 @@
+/*
+ This file is part of GNU Taler
+ (C) 2021-2023 Taler Systems S.A.
+
+ GNU Taler is free software; you can redistribute it and/or modify it under the
+ terms of the GNU General Public License as published by the Free Software
+ Foundation; either version 3, or (at your option) any later version.
+
+ GNU Taler is distributed in the hope that it will be useful, but WITHOUT ANY
+ WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
+ A PARTICULAR PURPOSE.  See the GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License along with
+ GNU Taler; see the file COPYING.  If not, see <http://www.gnu.org/licenses/>
+ */
+
+/**
+ *
+ * @author Sebastian Javier Marchano (sebasjm)
+ */
+
+import { useTranslationContext } from "@gnu-taler/web-util/browser";
+import { Fragment, h, VNode } from "preact";
+import { useState } from "preact/hooks";
+import { NotificationCard } from "../../../../components/menu/index.js";
+import { MerchantBackend } from "../../../../declaration.js";
+import { useReservesAPI } from "../../../../hooks/reserves.js";
+import { Notification } from "../../../../utils/types.js";
+import { CreatedSuccessfully } from "./CreatedSuccessfully.js";
+import { CreatePage } from "./CreatePage.js";
+interface Props {
+  onBack: () => void;
+  onConfirm: () => void;
+}
+export default function CreateReserve({ onBack, onConfirm }: Props): VNode {
+  const { createReserve } = useReservesAPI();
+  const [notif, setNotif] = useState<Notification | undefined>(undefined);
+  const { i18n } = useTranslationContext();
+
+  const [createdOk, setCreatedOk] = useState<
+    | {
+      request: MerchantBackend.Rewards.ReserveCreateRequest;
+      response: MerchantBackend.Rewards.ReserveCreateConfirmation;
+    }
+    | undefined
+  >(undefined);
+
+  if (createdOk) {
+    return <CreatedSuccessfully entity={createdOk} onConfirm={onConfirm} />;
+  }
+
+  return (
+    <Fragment>
+      <NotificationCard notification={notif} />
+      <CreatePage
+        onBack={onBack}
+        onCreate={(request: MerchantBackend.Rewards.ReserveCreateRequest) => {
+          return createReserve(request)
+            .then((r) => setCreatedOk({ request, response: r.data }))
+            .catch((error) => {
+              setNotif({
+                message: i18n.str`could not create reserve`,
+                type: "ERROR",
+                description: error.message,
+              });
+            });
+        }}
+      />
+    </Fragment>
+  );
+}
diff --git 
a/packages/auditor-backoffice-ui/src/paths/instance/reserves/details/DetailPage.tsx
 
b/packages/auditor-backoffice-ui/src/paths/instance/reserves/details/DetailPage.tsx
new file mode 100644
index 000000000..d8840eeac
--- /dev/null
+++ 
b/packages/auditor-backoffice-ui/src/paths/instance/reserves/details/DetailPage.tsx
@@ -0,0 +1,266 @@
+/*
+ This file is part of GNU Taler
+ (C) 2021-2023 Taler Systems S.A.
+
+ GNU Taler is free software; you can redistribute it and/or modify it under the
+ terms of the GNU General Public License as published by the Free Software
+ Foundation; either version 3, or (at your option) any later version.
+
+ GNU Taler is distributed in the hope that it will be useful, but WITHOUT ANY
+ WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
+ A PARTICULAR PURPOSE.  See the GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License along with
+ GNU Taler; see the file COPYING.  If not, see <http://www.gnu.org/licenses/>
+ */
+
+/**
+ *
+ * @author Sebastian Javier Marchano (sebasjm)
+ */
+
+import {
+  Amounts,
+  parsePaytoUri,
+  stringifyPaytoUri,
+} from "@gnu-taler/taler-util";
+import { useTranslationContext } from "@gnu-taler/web-util/browser";
+import { format } from "date-fns";
+import { Fragment, h, VNode } from "preact";
+import { useState } from "preact/hooks";
+import { QR } from "../../../../components/exception/QR.js";
+import { FormProvider } from "../../../../components/form/FormProvider.js";
+import { Input } from "../../../../components/form/Input.js";
+import { InputCurrency } from "../../../../components/form/InputCurrency.js";
+import { InputDate } from "../../../../components/form/InputDate.js";
+import { TextField } from "../../../../components/form/TextField.js";
+import { SimpleModal } from "../../../../components/modal/index.js";
+import { MerchantBackend } from "../../../../declaration.js";
+import { useRewardDetails } from "../../../../hooks/reserves.js";
+import { RewardInfo } from "./RewardInfo.js";
+import { ShowAccountsOfReserveAsQRWithLink } from 
"../create/CreatedSuccessfully.js";
+import { datetimeFormatForSettings, useSettings } from 
"../../../../hooks/useSettings.js";
+
+type Entity = MerchantBackend.Rewards.ReserveDetail;
+type CT = MerchantBackend.ContractTerms;
+
+interface Props {
+  onBack: () => void;
+  selected: Entity;
+  id: string;
+}
+
+export function DetailPage({ id, selected, onBack }: Props): VNode {
+  const { i18n } = useTranslationContext();
+  const didExchangeAckTransfer = Amounts.isNonZero(
+    Amounts.parseOrThrow(selected.exchange_initial_amount),
+  );
+
+  return (
+    <div class="columns">
+      <div class="column" />
+      <div class="column is-four-fifths">
+        <div class="section main-section">
+          <FormProvider object={{ ...selected, id }} valueHandler={null}>
+            <InputDate<Entity>
+              name="creation_time"
+              label={i18n.str`Created at`}
+              readonly
+            />
+            <InputDate<Entity>
+              name="expiration_time"
+              label={i18n.str`Valid until`}
+              readonly
+            />
+            <InputCurrency<Entity>
+              name="merchant_initial_amount"
+              label={i18n.str`Created balance`}
+              readonly
+            />
+            <TextField<Entity>
+              name="exchange_url"
+              label={i18n.str`Exchange URL`}
+              readonly
+            >
+              <a target="_blank" rel="noreferrer" href={selected.exchange_url}>
+                {selected.exchange_url}
+              </a>
+            </TextField>
+
+            {didExchangeAckTransfer && (
+              <Fragment>
+                <InputCurrency<Entity>
+                  name="exchange_initial_amount"
+                  label={i18n.str`Exchange balance`}
+                  readonly
+                />
+                <InputCurrency<Entity>
+                  name="pickup_amount"
+                  label={i18n.str`Picked up`}
+                  readonly
+                />
+                <InputCurrency<Entity>
+                  name="committed_amount"
+                  label={i18n.str`Committed`}
+                  readonly
+                />
+              </Fragment>
+            )}
+            <Input name="id" label={i18n.str`Subject`} readonly />
+          </FormProvider>
+
+          {didExchangeAckTransfer ? (
+            <Fragment>
+              <div class="card has-table">
+                <header class="card-header">
+                  <p class="card-header-title">
+                    <span class="icon">
+                      <i class="mdi mdi-cash-register" />
+                    </span>
+                    <i18n.Translate>Rewards</i18n.Translate>
+                  </p>
+                </header>
+                <div class="card-content">
+                  <div class="b-table has-pagination">
+                    <div class="table-wrapper has-mobile-cards">
+                      {selected.rewards && selected.rewards.length > 0 ? (
+                        <Table rewards={selected.rewards} />
+                      ) : (
+                        <EmptyTable />
+                      )}
+                    </div>
+                  </div>
+                </div>
+              </div>
+            </Fragment>
+          ) : selected.accounts ? (
+            <ShowAccountsOfReserveAsQRWithLink
+              accounts={selected.accounts}
+              amount={selected.merchant_initial_amount}
+              message={id}
+            />
+          ) : undefined}
+
+          <div class="buttons is-right mt-5">
+            <button class="button" onClick={onBack}>
+              <i18n.Translate>Back</i18n.Translate>
+            </button>
+          </div>
+        </div>
+      </div>
+      <div class="column" />
+    </div>
+  );
+}
+
+function EmptyTable(): VNode {
+  const { i18n } = useTranslationContext();
+  return (
+    <div class="content has-text-grey has-text-centered">
+      <p>
+        <span class="icon is-large">
+          <i class="mdi mdi-emoticon-sad mdi-48px" />
+        </span>
+      </p>
+      <p>
+        <i18n.Translate>
+          No reward has been authorized from this reserve
+        </i18n.Translate>
+      </p>
+    </div>
+  );
+}
+
+interface TableProps {
+  rewards: MerchantBackend.Rewards.RewardStatusEntry[];
+}
+
+function Table({ rewards }: TableProps): VNode {
+  const { i18n } = useTranslationContext();
+  return (
+    <div class="table-container">
+      <table class="table is-fullwidth is-striped is-hoverable is-fullwidth">
+        <thead>
+          <tr>
+            <th>
+              <i18n.Translate>Authorized</i18n.Translate>
+            </th>
+            <th>
+              <i18n.Translate>Picked up</i18n.Translate>
+            </th>
+            <th>
+              <i18n.Translate>Reason</i18n.Translate>
+            </th>
+            <th>
+              <i18n.Translate>Expiration</i18n.Translate>
+            </th>
+          </tr>
+        </thead>
+        <tbody>
+          {rewards.map((t, i) => {
+            return <RewardRow id={t.reward_id} key={i} entry={t} />;
+          })}
+        </tbody>
+      </table>
+    </div>
+  );
+}
+
+function RewardRow({
+  id,
+  entry,
+}: {
+  id: string;
+  entry: MerchantBackend.Rewards.RewardStatusEntry;
+}) {
+  const [selected, setSelected] = useState(false);
+  const result = useRewardDetails(id);
+  const [settings] = useSettings();
+  if (result.loading) {
+    return (
+      <tr>
+        <td>...</td>
+        <td>...</td>
+        <td>...</td>
+        <td>...</td>
+      </tr>
+    );
+  }
+  if (!result.ok) {
+    return (
+      <tr>
+        <td>...</td> {/* authorized */}
+        <td>{entry.total_amount}</td>
+        <td>{entry.reason}</td>
+        <td>...</td> {/* expired */}
+      </tr>
+    );
+  }
+  const info = result.data;
+  function onSelect() {
+    setSelected(true);
+  }
+  return (
+    <Fragment>
+      {selected && (
+        <SimpleModal
+          description="reward"
+          active
+          onCancel={() => setSelected(false)}
+        >
+          <RewardInfo id={id} amount={info.total_authorized} entity={info} />
+        </SimpleModal>
+      )}
+      <tr>
+        <td onClick={onSelect}>{info.total_authorized}</td>
+        <td onClick={onSelect}>{info.total_picked_up}</td>
+        <td onClick={onSelect}>{info.reason}</td>
+        <td onClick={onSelect}>
+          {info.expiration.t_s === "never"
+            ? "never"
+            : format(info.expiration.t_s * 1000, 
datetimeFormatForSettings(settings))}
+        </td>
+      </tr>
+    </Fragment>
+  );
+}
diff --git 
a/packages/auditor-backoffice-ui/src/paths/instance/reserves/details/Details.stories.tsx
 
b/packages/auditor-backoffice-ui/src/paths/instance/reserves/details/Details.stories.tsx
new file mode 100644
index 000000000..41c715f20
--- /dev/null
+++ 
b/packages/auditor-backoffice-ui/src/paths/instance/reserves/details/Details.stories.tsx
@@ -0,0 +1,126 @@
+/*
+ This file is part of GNU Taler
+ (C) 2021-2023 Taler Systems S.A.
+
+ GNU Taler is free software; you can redistribute it and/or modify it under the
+ terms of the GNU General Public License as published by the Free Software
+ Foundation; either version 3, or (at your option) any later version.
+
+ GNU Taler is distributed in the hope that it will be useful, but WITHOUT ANY
+ WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
+ A PARTICULAR PURPOSE.  See the GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License along with
+ GNU Taler; see the file COPYING.  If not, see <http://www.gnu.org/licenses/>
+ */
+
+/**
+ *
+ * @author Sebastian Javier Marchano (sebasjm)
+ */
+
+import { h, VNode, FunctionalComponent } from "preact";
+import { DetailPage as TestedComponent } from "./DetailPage.js";
+
+export default {
+  title: "Pages/Reserve/Detail",
+  component: TestedComponent,
+  argTypes: {
+    onUpdate: { action: "onUpdate" },
+    onBack: { action: "onBack" },
+  },
+};
+
+function createExample<Props>(
+  Component: FunctionalComponent<Props>,
+  props: Partial<Props>,
+) {
+  const r = (args: any) => <Component {...args} />;
+  r.args = props;
+  return r;
+}
+
+export const Funded = createExample(TestedComponent, {
+  id: "THISISTHERESERVEID",
+  selected: {
+    active: true,
+    committed_amount: "TESTKUDOS:10",
+    creation_time: {
+      t_s: new Date().getTime() / 1000,
+    },
+    exchange_initial_amount: "TESTKUDOS:10",
+    expiration_time: {
+      t_s: new Date().getTime() / 1000,
+    },
+    merchant_initial_amount: "TESTKUDOS:10",
+    pickup_amount: "TESTKUDOS:10",
+    accounts: [
+      {
+        payto_uri: "payto://x-taler-bank/bank.taler:8080/account",
+        credit_restrictions: [],
+        debit_restrictions: [],
+        master_sig: "",
+      },
+    ],
+    exchange_url: "http://exchange.taler/";,
+  },
+});
+
+export const NotYetFunded = createExample(TestedComponent, {
+  id: "THISISTHERESERVEID",
+  selected: {
+    active: true,
+    committed_amount: "TESTKUDOS:10",
+    creation_time: {
+      t_s: new Date().getTime() / 1000,
+    },
+    exchange_initial_amount: "TESTKUDOS:0",
+    expiration_time: {
+      t_s: new Date().getTime() / 1000,
+    },
+    merchant_initial_amount: "TESTKUDOS:10",
+    pickup_amount: "TESTKUDOS:10",
+    accounts: [
+      {
+        payto_uri: "payto://x-taler-bank/bank.taler:8080/account",
+        credit_restrictions: [],
+        debit_restrictions: [],
+        master_sig: "",
+      },
+    ],
+    exchange_url: "http://exchange.taler/";,
+  },
+});
+
+export const FundedWithEmptyRewards = createExample(TestedComponent, {
+  id: "THISISTHERESERVEID",
+  selected: {
+    active: true,
+    committed_amount: "TESTKUDOS:10",
+    creation_time: {
+      t_s: new Date().getTime() / 1000,
+    },
+    exchange_initial_amount: "TESTKUDOS:10",
+    expiration_time: {
+      t_s: new Date().getTime() / 1000,
+    },
+    merchant_initial_amount: "TESTKUDOS:10",
+    pickup_amount: "TESTKUDOS:10",
+    accounts: [
+      {
+        payto_uri: "payto://x-taler-bank/bank.taler:8080/account",
+        credit_restrictions: [],
+        debit_restrictions: [],
+        master_sig: "",
+      },
+    ],
+    exchange_url: "http://exchange.taler/";,
+    rewards: [
+      {
+        reason: "asdasd",
+        reward_id: "123",
+        total_amount: "TESTKUDOS:1",
+      },
+    ],
+  },
+});
diff --git 
a/packages/auditor-backoffice-ui/src/paths/instance/reserves/details/RewardInfo.tsx
 
b/packages/auditor-backoffice-ui/src/paths/instance/reserves/details/RewardInfo.tsx
new file mode 100644
index 000000000..780068a91
--- /dev/null
+++ 
b/packages/auditor-backoffice-ui/src/paths/instance/reserves/details/RewardInfo.tsx
@@ -0,0 +1,88 @@
+/*
+ This file is part of GNU Taler
+ (C) 2021-2023 Taler Systems S.A.
+
+ GNU Taler is free software; you can redistribute it and/or modify it under the
+ terms of the GNU General Public License as published by the Free Software
+ Foundation; either version 3, or (at your option) any later version.
+
+ GNU Taler is distributed in the hope that it will be useful, but WITHOUT ANY
+ WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
+ A PARTICULAR PURPOSE.  See the GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License along with
+ GNU Taler; see the file COPYING.  If not, see <http://www.gnu.org/licenses/>
+ */
+import { stringifyRewardUri } from "@gnu-taler/taler-util";
+import { format } from "date-fns";
+import { Fragment, h, VNode } from "preact";
+import { useBackendContext } from "../../../../context/backend.js";
+import { MerchantBackend } from "../../../../declaration.js";
+import { datetimeFormatForSettings, useSettings } from 
"../../../../hooks/useSettings.js";
+
+type Entity = MerchantBackend.Rewards.RewardDetails;
+
+interface Props {
+  id: string;
+  entity: Entity;
+  amount: string;
+}
+
+export function RewardInfo({ id: merchantRewardId, amount, entity }: Props): 
VNode {
+  const { url: backendURL } = useBackendContext()
+  const [settings] = useSettings();
+  const rewardURL = stringifyRewardUri({ merchantBaseUrl: backendURL, 
merchantRewardId })
+  return (
+    <Fragment>
+      <div class="field is-horizontal">
+        <div class="field-label is-normal">
+          <label class="label">Amount</label>
+        </div>
+        <div class="field-body is-flex-grow-3">
+          <div class="field">
+            <p class="control">
+              <input readonly class="input" value={amount} />
+            </p>
+          </div>
+        </div>
+      </div>
+      <div class="field is-horizontal">
+        <div class="field-label is-normal">
+          <label class="label">URL</label>
+        </div>
+        <div class="field-body is-flex-grow-3">
+          <div class="field" style={{ overflowWrap: "anywhere" }}>
+            <p class="control">
+              <a target="_blank" rel="noreferrer" href={rewardURL}>
+                {rewardURL}
+              </a>
+            </p>
+          </div>
+        </div>
+      </div>
+      <div class="field is-horizontal">
+        <div class="field-label is-normal">
+          <label class="label">Valid until</label>
+        </div>
+        <div class="field-body is-flex-grow-3">
+          <div class="field">
+            <p class="control">
+              <input
+                class="input"
+                readonly
+                value={
+                  !entity.expiration || entity.expiration.t_s === "never"
+                    ? "never"
+                    : format(
+                      entity.expiration.t_s * 1000,
+                      datetimeFormatForSettings(settings),
+                    )
+                }
+              />
+            </p>
+          </div>
+        </div>
+      </div>
+    </Fragment>
+  );
+}
diff --git 
a/packages/auditor-backoffice-ui/src/paths/instance/reserves/details/index.tsx 
b/packages/auditor-backoffice-ui/src/paths/instance/reserves/details/index.tsx
new file mode 100644
index 000000000..8e2a74529
--- /dev/null
+++ 
b/packages/auditor-backoffice-ui/src/paths/instance/reserves/details/index.tsx
@@ -0,0 +1,68 @@
+/*
+ This file is part of GNU Taler
+ (C) 2021-2023 Taler Systems S.A.
+
+ GNU Taler is free software; you can redistribute it and/or modify it under the
+ terms of the GNU General Public License as published by the Free Software
+ Foundation; either version 3, or (at your option) any later version.
+
+ GNU Taler is distributed in the hope that it will be useful, but WITHOUT ANY
+ WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
+ A PARTICULAR PURPOSE.  See the GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License along with
+ GNU Taler; see the file COPYING.  If not, see <http://www.gnu.org/licenses/>
+ */
+
+/**
+ *
+ * @author Sebastian Javier Marchano (sebasjm)
+ */
+
+import { ErrorType, HttpError } from "@gnu-taler/web-util/browser";
+import { Fragment, h, VNode } from "preact";
+import { Loading } from "../../../../components/exception/loading.js";
+import { MerchantBackend } from "../../../../declaration.js";
+import { useReserveDetails } from "../../../../hooks/reserves.js";
+import { DetailPage } from "./DetailPage.js";
+import { HttpStatusCode } from "@gnu-taler/taler-util";
+
+interface Props {
+  rid: string;
+
+  onUnauthorized: () => VNode;
+  onLoadError: (error: HttpError<MerchantBackend.ErrorDetail>) => VNode;
+  onNotFound: () => VNode;
+  onDelete: () => void;
+  onBack: () => void;
+}
+export default function DetailReserve({
+  rid,
+  onUnauthorized,
+  onLoadError,
+  onNotFound,
+  onBack,
+  onDelete,
+}: Props): VNode {
+  const result = useReserveDetails(rid);
+
+  if (result.loading) return <Loading />;
+  if (!result.ok) {
+    if (
+      result.type === ErrorType.CLIENT &&
+      result.status === HttpStatusCode.Unauthorized
+    )
+      return onUnauthorized();
+    if (
+      result.type === ErrorType.CLIENT &&
+      result.status === HttpStatusCode.NotFound
+    )
+      return onNotFound();
+    return onLoadError(result);
+  }
+  return (
+    <Fragment>
+      <DetailPage selected={result.data} onBack={onBack} id={rid} />
+    </Fragment>
+  );
+}
diff --git 
a/packages/auditor-backoffice-ui/src/paths/instance/reserves/list/AutorizeRewardModal.tsx
 
b/packages/auditor-backoffice-ui/src/paths/instance/reserves/list/AutorizeRewardModal.tsx
new file mode 100644
index 000000000..e205ee621
--- /dev/null
+++ 
b/packages/auditor-backoffice-ui/src/paths/instance/reserves/list/AutorizeRewardModal.tsx
@@ -0,0 +1,124 @@
+/*
+ This file is part of GNU Taler
+ (C) 2021-2023 Taler Systems S.A.
+
+ GNU Taler is free software; you can redistribute it and/or modify it under the
+ terms of the GNU General Public License as published by the Free Software
+ Foundation; either version 3, or (at your option) any later version.
+
+ GNU Taler is distributed in the hope that it will be useful, but WITHOUT ANY
+ WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
+ A PARTICULAR PURPOSE.  See the GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License along with
+ GNU Taler; see the file COPYING.  If not, see <http://www.gnu.org/licenses/>
+ */
+
+/**
+ *
+ * @author Sebastian Javier Marchano (sebasjm)
+ */
+
+import { useTranslationContext } from "@gnu-taler/web-util/browser";
+import { h, VNode } from "preact";
+import { useState } from "preact/hooks";
+import * as yup from "yup";
+import {
+  FormErrors,
+  FormProvider,
+} from "../../../../components/form/FormProvider.js";
+import { Input } from "../../../../components/form/Input.js";
+import { InputCurrency } from "../../../../components/form/InputCurrency.js";
+import {
+  ConfirmModal,
+  ContinueModal,
+} from "../../../../components/modal/index.js";
+import { MerchantBackend } from "../../../../declaration.js";
+import { AuthorizeRewardSchema } from "../../../../schemas/index.js";
+import { CreatedSuccessfully } from "./CreatedSuccessfully.js";
+
+interface AuthorizeRewardModalProps {
+  onCancel: () => void;
+  onConfirm: (value: MerchantBackend.Rewards.RewardCreateRequest) => void;
+  rewardAuthorized?: {
+    response: MerchantBackend.Rewards.RewardCreateConfirmation;
+    request: MerchantBackend.Rewards.RewardCreateRequest;
+  };
+}
+
+export function AuthorizeRewardModal({
+  onCancel,
+  onConfirm,
+  rewardAuthorized,
+}: AuthorizeRewardModalProps): VNode {
+  // const result = useOrderDetails(id)
+  type State = MerchantBackend.Rewards.RewardCreateRequest;
+  const [form, setValue] = useState<Partial<State>>({});
+  const { i18n } = useTranslationContext();
+
+  // const [errors, setErrors] = useState<FormErrors<State>>({})
+  let errors: FormErrors<State> = {};
+  try {
+    AuthorizeRewardSchema.validateSync(form, { abortEarly: false });
+  } catch (err) {
+    if (err instanceof yup.ValidationError) {
+      const yupErrors = err.inner as any[];
+      errors = yupErrors.reduce(
+        (prev, cur) =>
+          !cur.path ? prev : { ...prev, [cur.path]: cur.message },
+        {},
+      );
+    }
+  }
+  const hasErrors = Object.keys(errors).some(
+    (k) => (errors as any)[k] !== undefined,
+  );
+
+  const validateAndConfirm = () => {
+    onConfirm(form as State);
+  };
+  if (rewardAuthorized) {
+    return (
+      <ContinueModal description="reward" active onConfirm={onCancel}>
+        <CreatedSuccessfully
+          entity={rewardAuthorized.response}
+          request={rewardAuthorized.request}
+          onConfirm={onCancel}
+        />
+      </ContinueModal>
+    );
+  }
+
+  return (
+    <ConfirmModal
+      description="New reward"
+      active
+      onCancel={onCancel}
+      disabled={hasErrors}
+      onConfirm={validateAndConfirm}
+    >
+      <FormProvider<State>
+        errors={errors}
+        object={form}
+        valueHandler={setValue}
+      >
+        <InputCurrency<State>
+          name="amount"
+          label={i18n.str`Amount`}
+          tooltip={i18n.str`amount of reward`}
+        />
+        <Input<State>
+          name="justification"
+          label={i18n.str`Justification`}
+          inputType="multiline"
+          tooltip={i18n.str`reason for the reward`}
+        />
+        <Input<State>
+          name="next_url"
+          label={i18n.str`URL after reward`}
+          tooltip={i18n.str`URL to visit after reward payment`}
+        />
+      </FormProvider>
+    </ConfirmModal>
+  );
+}
diff --git 
a/packages/auditor-backoffice-ui/src/paths/instance/reserves/list/CreatedSuccessfully.tsx
 
b/packages/auditor-backoffice-ui/src/paths/instance/reserves/list/CreatedSuccessfully.tsx
new file mode 100644
index 000000000..b78236bc7
--- /dev/null
+++ 
b/packages/auditor-backoffice-ui/src/paths/instance/reserves/list/CreatedSuccessfully.tsx
@@ -0,0 +1,102 @@
+/*
+ This file is part of GNU Taler
+ (C) 2021-2023 Taler Systems S.A.
+
+ GNU Taler is free software; you can redistribute it and/or modify it under the
+ terms of the GNU General Public License as published by the Free Software
+ Foundation; either version 3, or (at your option) any later version.
+
+ GNU Taler is distributed in the hope that it will be useful, but WITHOUT ANY
+ WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
+ A PARTICULAR PURPOSE.  See the GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License along with
+ GNU Taler; see the file COPYING.  If not, see <http://www.gnu.org/licenses/>
+ */
+import { format } from "date-fns";
+import { Fragment, h, VNode } from "preact";
+import { CreatedSuccessfully as Template } from 
"../../../../components/notifications/CreatedSuccessfully.js";
+import { MerchantBackend } from "../../../../declaration.js";
+import { datetimeFormatForSettings, useSettings } from 
"../../../../hooks/useSettings.js";
+
+type Entity = MerchantBackend.Rewards.RewardCreateConfirmation;
+
+interface Props {
+  entity: Entity;
+  request: MerchantBackend.Rewards.RewardCreateRequest;
+  onConfirm: () => void;
+  onCreateAnother?: () => void;
+}
+
+export function CreatedSuccessfully({
+  request,
+  entity,
+  onConfirm,
+  onCreateAnother,
+}: Props): VNode {
+  const [settings] = useSettings();
+  return (
+    <Fragment>
+      <div class="field is-horizontal">
+        <div class="field-label is-normal">
+          <label class="label">Amount</label>
+        </div>
+        <div class="field-body is-flex-grow-3">
+          <div class="field">
+            <p class="control">
+              <input readonly class="input" value={request.amount} />
+            </p>
+          </div>
+        </div>
+      </div>
+      <div class="field is-horizontal">
+        <div class="field-label is-normal">
+          <label class="label">Justification</label>
+        </div>
+        <div class="field-body is-flex-grow-3">
+          <div class="field">
+            <p class="control">
+              <input readonly class="input" value={request.justification} />
+            </p>
+          </div>
+        </div>
+      </div>
+      <div class="field is-horizontal">
+        <div class="field-label is-normal">
+          <label class="label">URL</label>
+        </div>
+        <div class="field-body is-flex-grow-3">
+          <div class="field">
+            <p class="control">
+              <input readonly class="input" value={entity.reward_status_url} />
+            </p>
+          </div>
+        </div>
+      </div>
+      <div class="field is-horizontal">
+        <div class="field-label is-normal">
+          <label class="label">Valid until</label>
+        </div>
+        <div class="field-body is-flex-grow-3">
+          <div class="field">
+            <p class="control">
+              <input
+                class="input"
+                readonly
+                value={
+                  !entity.reward_expiration ||
+                    entity.reward_expiration.t_s === "never"
+                    ? "never"
+                    : format(
+                      entity.reward_expiration.t_s * 1000,
+                      datetimeFormatForSettings(settings),
+                    )
+                }
+              />
+            </p>
+          </div>
+        </div>
+      </div>
+    </Fragment>
+  );
+}
diff --git 
a/packages/auditor-backoffice-ui/src/paths/instance/reserves/list/List.stories.tsx
 
b/packages/auditor-backoffice-ui/src/paths/instance/reserves/list/List.stories.tsx
new file mode 100644
index 000000000..b070bbde3
--- /dev/null
+++ 
b/packages/auditor-backoffice-ui/src/paths/instance/reserves/list/List.stories.tsx
@@ -0,0 +1,96 @@
+/*
+ This file is part of GNU Taler
+ (C) 2021-2023 Taler Systems S.A.
+
+ GNU Taler is free software; you can redistribute it and/or modify it under the
+ terms of the GNU General Public License as published by the Free Software
+ Foundation; either version 3, or (at your option) any later version.
+
+ GNU Taler is distributed in the hope that it will be useful, but WITHOUT ANY
+ WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
+ A PARTICULAR PURPOSE.  See the GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License along with
+ GNU Taler; see the file COPYING.  If not, see <http://www.gnu.org/licenses/>
+ */
+
+/**
+ *
+ * @author Sebastian Javier Marchano (sebasjm)
+ */
+
+import { h, VNode, FunctionalComponent } from "preact";
+import { CardTable as TestedComponent } from "./Table.js";
+
+export default {
+  title: "Pages/Reserve/List",
+  component: TestedComponent,
+};
+
+function createExample<Props>(
+  Component: FunctionalComponent<Props>,
+  props: Partial<Props>,
+) {
+  const r = (args: any) => <Component {...args} />;
+  r.args = props;
+  return r;
+}
+
+export const AllFunded = createExample(TestedComponent, {
+  instances: [
+    {
+      id: "reseverId",
+      active: true,
+      committed_amount: "TESTKUDOS:10",
+      creation_time: {
+        t_s: new Date().getTime() / 1000,
+      },
+      exchange_initial_amount: "TESTKUDOS:10",
+      expiration_time: {
+        t_s: new Date().getTime() / 1000,
+      },
+      merchant_initial_amount: "TESTKUDOS:10",
+      pickup_amount: "TESTKUDOS:10",
+      reserve_pub: "WEQWDASDQWEASDADASDQWEQWEASDAS",
+    },
+    {
+      id: "reseverId2",
+      active: true,
+      committed_amount: "TESTKUDOS:13",
+      creation_time: {
+        t_s: new Date().getTime() / 1000,
+      },
+      exchange_initial_amount: "TESTKUDOS:10",
+      expiration_time: {
+        t_s: new Date().getTime() / 1000,
+      },
+      merchant_initial_amount: "TESTKUDOS:10",
+      pickup_amount: "TESTKUDOS:10",
+      reserve_pub: "WEQWDASDQWEASDADASDQWEQWEASDAS",
+    },
+  ],
+});
+
+export const Empty = createExample(TestedComponent, {
+  instances: [],
+});
+
+export const OneNotYetFunded = createExample(TestedComponent, {
+  instances: [
+    {
+      id: "reseverId",
+      active: true,
+      committed_amount: "TESTKUDOS:0",
+      creation_time: {
+        t_s: new Date().getTime() / 1000,
+      },
+      exchange_initial_amount: "TESTKUDOS:0",
+      expiration_time: {
+        t_s: new Date().getTime() / 1000,
+      },
+      merchant_initial_amount: "TESTKUDOS:10",
+      pickup_amount: "TESTKUDOS:10",
+      reserve_pub: "WEQWDASDQWEASDADASDQWEQWEASDAS",
+    },
+  ],
+});
diff --git 
a/packages/auditor-backoffice-ui/src/paths/instance/reserves/list/Table.tsx 
b/packages/auditor-backoffice-ui/src/paths/instance/reserves/list/Table.tsx
new file mode 100644
index 000000000..795e7ec82
--- /dev/null
+++ b/packages/auditor-backoffice-ui/src/paths/instance/reserves/list/Table.tsx
@@ -0,0 +1,320 @@
+/*
+ This file is part of GNU Taler
+ (C) 2021-2023 Taler Systems S.A.
+
+ GNU Taler is free software; you can redistribute it and/or modify it under the
+ terms of the GNU General Public License as published by the Free Software
+ Foundation; either version 3, or (at your option) any later version.
+
+ GNU Taler is distributed in the hope that it will be useful, but WITHOUT ANY
+ WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
+ A PARTICULAR PURPOSE.  See the GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License along with
+ GNU Taler; see the file COPYING.  If not, see <http://www.gnu.org/licenses/>
+ */
+
+/**
+ *
+ * @author Sebastian Javier Marchano (sebasjm)
+ */
+
+import { useTranslationContext } from "@gnu-taler/web-util/browser";
+import { format } from "date-fns";
+import { Fragment, h, VNode } from "preact";
+import { MerchantBackend, WithId } from "../../../../declaration.js";
+import { datetimeFormatForSettings, useSettings } from 
"../../../../hooks/useSettings.js";
+
+type Entity = MerchantBackend.Rewards.ReserveStatusEntry & WithId;
+
+interface Props {
+  instances: Entity[];
+  onNewReward: (id: Entity) => void;
+  onSelect: (id: Entity) => void;
+  onDelete: (id: Entity) => void;
+  onCreate: () => void;
+}
+
+export function CardTable({
+  instances,
+  onCreate,
+  onSelect,
+  onNewReward,
+  onDelete,
+}: Props): VNode {
+  const [withoutFunds, withFunds] = instances.reduce((prev, current) => {
+    const amount = current.exchange_initial_amount;
+    if (amount.endsWith(":0")) {
+      prev[0] = prev[0].concat(current);
+    } else {
+      prev[1] = prev[1].concat(current);
+    }
+    return prev;
+  }, new Array<Array<Entity>>([], []));
+
+  const { i18n } = useTranslationContext();
+
+  return (
+    <Fragment>
+      {withoutFunds.length > 0 && (
+        <div class="card has-table">
+          <header class="card-header">
+            <p class="card-header-title">
+              <span class="icon">
+                <i class="mdi mdi-cash" />
+              </span>
+              <i18n.Translate>Reserves not yet funded</i18n.Translate>
+            </p>
+          </header>
+          <div class="card-content">
+            <div class="b-table has-pagination">
+              <div class="table-wrapper has-mobile-cards">
+                <TableWithoutFund
+                  instances={withoutFunds}
+                  onNewReward={onNewReward}
+                  onSelect={onSelect}
+                  onDelete={onDelete}
+                />
+              </div>
+            </div>
+          </div>
+        </div>
+      )}
+
+      <div class="card has-table">
+        <header class="card-header">
+          <p class="card-header-title">
+            <span class="icon">
+              <i class="mdi mdi-cash" />
+            </span>
+            <i18n.Translate>Reserves ready</i18n.Translate>
+          </p>
+          <div class="card-header-icon" aria-label="more options" />
+          <div class="card-header-icon" aria-label="more options">
+            <span
+              class="has-tooltip-left"
+              data-tooltip={i18n.str`add new reserve`}
+            >
+              <button class="button is-info" type="button" onClick={onCreate}>
+                <span class="icon is-small">
+                  <i class="mdi mdi-plus mdi-36px" />
+                </span>
+              </button>
+            </span>
+          </div>
+        </header>
+        <div class="card-content">
+          <div class="b-table has-pagination">
+            <div class="table-wrapper has-mobile-cards">
+              {withFunds.length > 0 ? (
+                <Table
+                  instances={withFunds}
+                  onNewReward={onNewReward}
+                  onSelect={onSelect}
+                  onDelete={onDelete}
+                />
+              ) : (
+                <EmptyTable />
+              )}
+            </div>
+          </div>
+        </div>
+      </div>
+    </Fragment>
+  );
+}
+interface TableProps {
+  instances: Entity[];
+  onNewReward: (id: Entity) => void;
+  onDelete: (id: Entity) => void;
+  onSelect: (id: Entity) => void;
+}
+
+function Table({ instances, onNewReward, onSelect, onDelete }: TableProps): 
VNode {
+  const { i18n } = useTranslationContext();
+  const [settings] = useSettings();
+  return (
+    <div class="table-container">
+      <table class="table is-fullwidth is-striped is-hoverable is-fullwidth">
+        <thead>
+          <tr>
+            <th>
+              <i18n.Translate>Created at</i18n.Translate>
+            </th>
+            <th>
+              <i18n.Translate>Expires at</i18n.Translate>
+            </th>
+            <th>
+              <i18n.Translate>Initial</i18n.Translate>
+            </th>
+            <th>
+              <i18n.Translate>Picked up</i18n.Translate>
+            </th>
+            <th>
+              <i18n.Translate>Committed</i18n.Translate>
+            </th>
+            <th />
+          </tr>
+        </thead>
+        <tbody>
+          {instances.map((i) => {
+            return (
+              <tr key={i.id}>
+                <td
+                  onClick={(): void => onSelect(i)}
+                  style={{ cursor: "pointer" }}
+                >
+                  {i.creation_time.t_s === "never"
+                    ? "never"
+                    : format(i.creation_time.t_s * 1000, 
datetimeFormatForSettings(settings))}
+                </td>
+                <td
+                  onClick={(): void => onSelect(i)}
+                  style={{ cursor: "pointer" }}
+                >
+                  {i.expiration_time.t_s === "never"
+                    ? "never"
+                    : format(
+                      i.expiration_time.t_s * 1000,
+                      datetimeFormatForSettings(settings),
+                    )}
+                </td>
+                <td
+                  onClick={(): void => onSelect(i)}
+                  style={{ cursor: "pointer" }}
+                >
+                  {i.exchange_initial_amount}
+                </td>
+                <td
+                  onClick={(): void => onSelect(i)}
+                  style={{ cursor: "pointer" }}
+                >
+                  {i.pickup_amount}
+                </td>
+                <td
+                  onClick={(): void => onSelect(i)}
+                  style={{ cursor: "pointer" }}
+                >
+                  {i.committed_amount}
+                </td>
+                <td class="is-actions-cell right-sticky">
+                  <div class="buttons is-right">
+                    <button
+                      class="button is-small is-danger has-tooltip-left"
+                      data-tooltip={i18n.str`delete selected reserve from the 
database`}
+                      type="button"
+                      onClick={(): void => onDelete(i)}
+                    >
+                      Delete
+                    </button>
+                    <button
+                      class="button is-small is-info has-tooltip-left"
+                      data-tooltip={i18n.str`authorize new reward from 
selected reserve`}
+                      type="button"
+                      onClick={(): void => onNewReward(i)}
+                    >
+                      New Reward
+                    </button>
+                  </div>
+                </td>
+              </tr>
+            );
+          })}
+        </tbody>
+      </table>
+    </div>
+  );
+}
+
+function EmptyTable(): VNode {
+  const { i18n } = useTranslationContext();
+  return (
+    <div class="content has-text-grey has-text-centered">
+      <p>
+        <span class="icon is-large">
+          <i class="mdi mdi-emoticon-sad mdi-48px" />
+        </span>
+      </p>
+      <p>
+        <i18n.Translate>
+          There is no ready reserves yet, add more pressing the + sign or fund
+          them
+        </i18n.Translate>
+      </p>
+    </div>
+  );
+}
+
+function TableWithoutFund({
+  instances,
+  onSelect,
+  onDelete,
+}: TableProps): VNode {
+  const { i18n } = useTranslationContext();
+  const [settings] = useSettings();
+  return (
+    <div class="table-container">
+      <table class="table is-fullwidth is-striped is-hoverable is-fullwidth">
+        <thead>
+          <tr>
+            <th>
+              <i18n.Translate>Created at</i18n.Translate>
+            </th>
+            <th>
+              <i18n.Translate>Expires at</i18n.Translate>
+            </th>
+            <th>
+              <i18n.Translate>Expected Balance</i18n.Translate>
+            </th>
+            <th />
+          </tr>
+        </thead>
+        <tbody>
+          {instances.map((i) => {
+            return (
+              <tr key={i.id}>
+                <td
+                  onClick={(): void => onSelect(i)}
+                  style={{ cursor: "pointer" }}
+                >
+                  {i.creation_time.t_s === "never"
+                    ? "never"
+                    : format(i.creation_time.t_s * 1000, 
datetimeFormatForSettings(settings))}
+                </td>
+                <td
+                  onClick={(): void => onSelect(i)}
+                  style={{ cursor: "pointer" }}
+                >
+                  {i.expiration_time.t_s === "never"
+                    ? "never"
+                    : format(
+                      i.expiration_time.t_s * 1000,
+                      datetimeFormatForSettings(settings),
+                    )}
+                </td>
+                <td
+                  onClick={(): void => onSelect(i)}
+                  style={{ cursor: "pointer" }}
+                >
+                  {i.merchant_initial_amount}
+                </td>
+                <td class="is-actions-cell right-sticky">
+                  <div class="buttons is-right">
+                    <button
+                      class="button is-small is-danger jb-modal 
has-tooltip-left"
+                      type="button"
+                      data-tooltip={i18n.str`delete selected reserve from the 
database`}
+                      onClick={(): void => onDelete(i)}
+                    >
+                      Delete
+                    </button>
+                  </div>
+                </td>
+              </tr>
+            );
+          })}
+        </tbody>
+      </table>
+    </div>
+  );
+}
diff --git 
a/packages/auditor-backoffice-ui/src/paths/instance/reserves/list/index.tsx 
b/packages/auditor-backoffice-ui/src/paths/instance/reserves/list/index.tsx
new file mode 100644
index 000000000..b26ff0000
--- /dev/null
+++ b/packages/auditor-backoffice-ui/src/paths/instance/reserves/list/index.tsx
@@ -0,0 +1,171 @@
+/*
+ This file is part of GNU Taler
+ (C) 2021-2023 Taler Systems S.A.
+
+ GNU Taler is free software; you can redistribute it and/or modify it under the
+ terms of the GNU General Public License as published by the Free Software
+ Foundation; either version 3, or (at your option) any later version.
+
+ GNU Taler is distributed in the hope that it will be useful, but WITHOUT ANY
+ WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
+ A PARTICULAR PURPOSE.  See the GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License along with
+ GNU Taler; see the file COPYING.  If not, see <http://www.gnu.org/licenses/>
+ */
+
+/**
+ *
+ * @author Sebastian Javier Marchano (sebasjm)
+ */
+
+import {
+  ErrorType,
+  HttpError,
+  useTranslationContext,
+} from "@gnu-taler/web-util/browser";
+import { h, VNode } from "preact";
+import { useState } from "preact/hooks";
+import { Loading } from "../../../../components/exception/loading.js";
+import { NotificationCard } from "../../../../components/menu/index.js";
+import { MerchantBackend } from "../../../../declaration.js";
+import {
+  useInstanceReserves,
+  useReservesAPI,
+} from "../../../../hooks/reserves.js";
+import { Notification } from "../../../../utils/types.js";
+import { AuthorizeRewardModal } from "./AutorizeRewardModal.js";
+import { CardTable } from "./Table.js";
+import { HttpStatusCode } from "@gnu-taler/taler-util";
+import { ConfirmModal } from "../../../../components/modal/index.js";
+
+interface Props {
+  onUnauthorized: () => VNode;
+  onLoadError: (e: HttpError<MerchantBackend.ErrorDetail>) => VNode;
+  onSelect: (id: string) => void;
+  onNotFound: () => VNode;
+  onCreate: () => void;
+}
+
+interface RewardConfirmation {
+  response: MerchantBackend.Rewards.RewardCreateConfirmation;
+  request: MerchantBackend.Rewards.RewardCreateRequest;
+}
+
+export default function ListRewards({
+  onUnauthorized,
+  onLoadError,
+  onNotFound,
+  onSelect,
+  onCreate,
+}: Props): VNode {
+  const result = useInstanceReserves();
+  const { deleteReserve, authorizeRewardReserve } = useReservesAPI();
+  const [notif, setNotif] = useState<Notification | undefined>(undefined);
+  const { i18n } = useTranslationContext();
+  const [reserveForReward, setReserveForReward] = useState<string | undefined>(
+    undefined,
+  );
+  const [deleting, setDeleting] =
+    useState<MerchantBackend.Rewards.ReserveStatusEntry | null>(null);
+  const [rewardAuthorized, setRewardAuthorized] = useState<
+    RewardConfirmation | undefined
+  >(undefined);
+
+  if (result.loading) return <Loading />;
+  if (!result.ok) {
+    if (
+      result.type === ErrorType.CLIENT &&
+      result.status === HttpStatusCode.Unauthorized
+    )
+      return onUnauthorized();
+    if (
+      result.type === ErrorType.CLIENT &&
+      result.status === HttpStatusCode.NotFound
+    )
+      return onNotFound();
+    return onLoadError(result);
+  }
+
+  return (
+    <section class="section is-main-section">
+      <NotificationCard notification={notif} />
+
+      {reserveForReward && (
+        <AuthorizeRewardModal
+          onCancel={() => {
+            setReserveForReward(undefined);
+            setRewardAuthorized(undefined);
+          }}
+          rewardAuthorized={rewardAuthorized}
+          onConfirm={async (request) => {
+            try {
+              const response = await authorizeRewardReserve(
+                reserveForReward,
+                request,
+              );
+              setRewardAuthorized({
+                request,
+                response: response.data,
+              });
+            } catch (error) {
+              setNotif({
+                message: i18n.str`could not create the reward`,
+                type: "ERROR",
+                description: error instanceof Error ? error.message : 
undefined,
+              });
+              setReserveForReward(undefined);
+            }
+          }}
+        />
+      )}
+
+      <CardTable
+        instances={result.data.reserves
+          .filter((r) => r.active)
+          .map((o) => ({ ...o, id: o.reserve_pub }))}
+        onCreate={onCreate}
+        onDelete={(reserve) => {
+          setDeleting(reserve)
+        }}
+        onSelect={(reserve) => onSelect(reserve.id)}
+        onNewReward={(reserve) => setReserveForReward(reserve.id)}
+      />
+
+      {deleting && (
+        <ConfirmModal
+          label={`Delete reserve`}
+          description={`Delete the reserve`}
+          danger
+          active
+          onCancel={() => setDeleting(null)}
+          onConfirm={async (): Promise<void> => {
+            try {
+              await deleteReserve(deleting.reserve_pub);
+              setNotif({
+                message: i18n.str`Reserve for 
"${deleting.merchant_initial_amount}" (ID: ${deleting.reserve_pub}) has been 
deleted`,
+                type: "SUCCESS",
+              });
+            } catch (error) {
+              setNotif({
+                message: i18n.str`Failed to delete reserve`,
+                type: "ERROR",
+                description: error instanceof Error ? error.message : 
undefined,
+              });
+            }
+            setDeleting(null);
+          }}
+        >
+          <p>
+            If you delete the reserve for 
<b>&quot;{deleting.merchant_initial_amount}&quot;</b> you won't be able to 
create more rewards. <br />
+            Reserve ID: <b>{deleting.reserve_pub}</b>
+          </p>
+          <p class="warning">
+            Deleting an template <b>cannot be undone</b>.
+          </p>
+        </ConfirmModal>
+      )}
+
+    </section>
+  );
+}
diff --git 
a/packages/auditor-backoffice-ui/src/paths/instance/templates/create/Create.stories.tsx
 
b/packages/auditor-backoffice-ui/src/paths/instance/templates/create/Create.stories.tsx
new file mode 100644
index 000000000..c9d17ea3b
--- /dev/null
+++ 
b/packages/auditor-backoffice-ui/src/paths/instance/templates/create/Create.stories.tsx
@@ -0,0 +1,28 @@
+/*
+ This file is part of GNU Taler
+ (C) 2021-2023 Taler Systems S.A.
+
+ GNU Taler is free software; you can redistribute it and/or modify it under the
+ terms of the GNU General Public License as published by the Free Software
+ Foundation; either version 3, or (at your option) any later version.
+
+ GNU Taler is distributed in the hope that it will be useful, but WITHOUT ANY
+ WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
+ A PARTICULAR PURPOSE.  See the GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License along with
+ GNU Taler; see the file COPYING.  If not, see <http://www.gnu.org/licenses/>
+ */
+
+/**
+ *
+ * @author Sebastian Javier Marchano (sebasjm)
+ */
+
+import { h, VNode, FunctionalComponent } from "preact";
+import { CreatePage as TestedComponent } from "./CreatePage.js";
+
+export default {
+  title: "Pages/Templates/Create",
+  component: TestedComponent,
+};
diff --git 
a/packages/auditor-backoffice-ui/src/paths/instance/templates/create/CreatePage.tsx
 
b/packages/auditor-backoffice-ui/src/paths/instance/templates/create/CreatePage.tsx
new file mode 100644
index 000000000..947f3572c
--- /dev/null
+++ 
b/packages/auditor-backoffice-ui/src/paths/instance/templates/create/CreatePage.tsx
@@ -0,0 +1,259 @@
+/*
+ This file is part of GNU Taler
+ (C) 2021-2023 Taler Systems S.A.
+
+ GNU Taler is free software; you can redistribute it and/or modify it under the
+ terms of the GNU General Public License as published by the Free Software
+ Foundation; either version 3, or (at your option) any later version.
+
+ GNU Taler is distributed in the hope that it will be useful, but WITHOUT ANY
+ WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
+ A PARTICULAR PURPOSE.  See the GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License along with
+ GNU Taler; see the file COPYING.  If not, see <http://www.gnu.org/licenses/>
+ */
+
+/**
+ *
+ * @author Sebastian Javier Marchano (sebasjm)
+ */
+
+import {
+  Amounts,
+  MerchantTemplateContractDetails,
+} from "@gnu-taler/taler-util";
+import { useTranslationContext } from "@gnu-taler/web-util/browser";
+import { Fragment, VNode, h } from "preact";
+import { useState } from "preact/hooks";
+import { AsyncButton } from "../../../../components/exception/AsyncButton.js";
+import {
+  FormErrors,
+  FormProvider,
+} from "../../../../components/form/FormProvider.js";
+import { Input } from "../../../../components/form/Input.js";
+import { InputCurrency } from "../../../../components/form/InputCurrency.js";
+import { InputDuration } from "../../../../components/form/InputDuration.js";
+import { InputNumber } from "../../../../components/form/InputNumber.js";
+import { InputSearchOnList } from 
"../../../../components/form/InputSearchOnList.js";
+import { InputWithAddon } from "../../../../components/form/InputWithAddon.js";
+import { useBackendContext } from "../../../../context/backend.js";
+import { MerchantBackend } from "../../../../declaration.js";
+import { useInstanceOtpDevices } from "../../../../hooks/otp.js";
+import { undefinedIfEmpty } from "../../../../utils/table.js";
+import { InputTab } from "../../../../components/form/InputTab.js";
+
+enum Steps {
+  BOTH_FIXED,
+  FIXED_PRICE,
+  FIXED_SUMMARY,
+  NON_FIXED,
+}
+
+type Entity = MerchantBackend.Template.TemplateAddDetails & { type: Steps };
+
+interface Props {
+  onCreate: (d: Entity) => Promise<void>;
+  onBack?: () => void;
+}
+
+export function CreatePage({ onCreate, onBack }: Props): VNode {
+  const { i18n } = useTranslationContext();
+  const { url: backendURL } = useBackendContext()
+  const devices = useInstanceOtpDevices()
+
+  const [state, setState] = useState<Partial<Entity>>({
+    template_contract: {
+      minimum_age: 0,
+      pay_duration: {
+        d_us: 1000 * 1000 * 60 * 30, //30 min
+      },
+    },
+    type: Steps.NON_FIXED,
+  });
+
+  const parsedPrice = !state.template_contract?.amount
+    ? undefined
+    : Amounts.parse(state.template_contract?.amount);
+
+  const errors: FormErrors<Entity> = {
+    template_id: !state.template_id
+      ? i18n.str`should not be empty`
+      : !/[a-zA-Z0-9]*/.test(state.template_id)
+        ? i18n.str`no valid. only characters and numbers`
+        : undefined,
+    template_description: !state.template_description
+      ? i18n.str`should not be empty`
+      : undefined,
+    template_contract: !state.template_contract
+      ? undefined
+      : undefinedIfEmpty({
+        amount: !(state.type === Steps.FIXED_PRICE || state.type === 
Steps.BOTH_FIXED)
+          ? undefined
+          : !state.template_contract?.amount
+            ? i18n.str`required`
+            : !parsedPrice
+              ? i18n.str`not valid`
+              : Amounts.isZero(parsedPrice)
+                ? i18n.str`must be greater than 0`
+                : undefined,
+        summary: !(state.type === Steps.FIXED_SUMMARY || state.type === 
Steps.BOTH_FIXED)
+          ? undefined
+          : !state.template_contract?.summary
+            ? i18n.str`required`
+            : undefined,
+        minimum_age:
+          state.template_contract.minimum_age < 0
+            ? i18n.str`should be greater that 0`
+            : undefined,
+        pay_duration: !state.template_contract.pay_duration
+          ? i18n.str`can't be empty`
+          : state.template_contract.pay_duration.d_us === "forever"
+            ? undefined
+            : state.template_contract.pay_duration.d_us < 1000 * 1000 //less 
than one second
+              ? i18n.str`to short`
+              : undefined,
+      } as Partial<MerchantTemplateContractDetails>),
+  };
+
+  const hasErrors = Object.keys(errors).some(
+    (k) => (errors as any)[k] !== undefined,
+  );
+
+  const submitForm = () => {
+    if (hasErrors) return Promise.reject();
+    if (state.template_contract) {
+      if (state.type === Steps.NON_FIXED) {
+        delete state.template_contract.amount;
+        delete state.template_contract.summary;
+      } else if (state.type === Steps.FIXED_SUMMARY) {
+        delete state.template_contract.amount;
+      } else if (state.type === Steps.FIXED_PRICE) {
+        delete state.template_contract.summary;
+      }
+    }
+    delete state.type
+    return onCreate(state as any);
+  };
+
+  const deviceList = !devices.ok ? [] : devices.data.otp_devices
+
+  return (
+    <div>
+      <section class="section is-main-section">
+        <div class="columns">
+          <div class="column" />
+          <div class="column is-four-fifths">
+            <FormProvider
+              object={state}
+              valueHandler={setState}
+              errors={errors}
+            >
+              <InputWithAddon<Entity>
+                name="template_id"
+                help={`${backendURL}/templates/${state.template_id ?? ""}`}
+                label={i18n.str`Identifier`}
+                tooltip={i18n.str`Name of the template in URLs.`}
+              />
+              <Input<Entity>
+                name="template_description"
+                label={i18n.str`Description`}
+                help=""
+                tooltip={i18n.str`Describe what this template stands for`}
+              />
+              <InputTab
+                name="type"
+                label={i18n.str`Type`}
+                help={(() => {
+                  switch (state.type) {
+                    case Steps.NON_FIXED: return i18n.str`User will be able to 
input price and summary before payment.`
+                    case Steps.FIXED_PRICE: return i18n.str`User will be able 
to add a summary before payment.`
+                    case Steps.FIXED_SUMMARY: return i18n.str`User will be 
able to set the price before payment.`
+                    case Steps.BOTH_FIXED: return i18n.str`User will not be 
able to change the price or the summary.`
+                  }
+                })()}
+                tooltip={i18n.str`Define what the user be allowed to modify`}
+                values={[
+                  Steps.NON_FIXED,
+                  Steps.FIXED_PRICE,
+                  Steps.FIXED_SUMMARY,
+                  Steps.BOTH_FIXED,
+                ]}
+                toStr={(v: Steps): string => {
+                  switch (v) {
+                    case Steps.NON_FIXED: return i18n.str`Simple`
+                    case Steps.FIXED_PRICE: return i18n.str`With price`
+                    case Steps.FIXED_SUMMARY: return i18n.str`With summary`
+                    case Steps.BOTH_FIXED: return i18n.str`With price and 
summary`
+                  }
+                }}
+              />
+              {state.type === Steps.BOTH_FIXED || state.type === 
Steps.FIXED_SUMMARY ?
+                <Input
+                  name="template_contract.summary"
+                  inputType="multiline"
+                  label={i18n.str`Fixed summary`}
+                  tooltip={i18n.str`If specified, this template will create 
order with the same summary`}
+                />
+                : undefined}
+              {state.type === Steps.BOTH_FIXED || state.type === 
Steps.FIXED_PRICE ?
+                <InputCurrency
+                  name="template_contract.amount"
+                  label={i18n.str`Fixed price`}
+                  tooltip={i18n.str`If specified, this template will create 
order with the same price`}
+                />
+                : undefined}
+              <InputNumber
+                name="template_contract.minimum_age"
+                label={i18n.str`Minimum age`}
+                help=""
+                tooltip={i18n.str`Is this contract restricted to some age?`}
+              />
+              <InputDuration
+                name="template_contract.pay_duration"
+                label={i18n.str`Payment timeout`}
+                help=""
+                tooltip={i18n.str`How much time has the customer to complete 
the payment once the order was created.`}
+              />
+              <Input<Entity>
+                name="otp_id"
+                label={i18n.str`OTP device`}
+                readonly
+                tooltip={i18n.str`Use to verify transaction in offline mode.`}
+              />
+              <InputSearchOnList
+                label={i18n.str`Search device`}
+                onChange={(p) => setState((v) => ({ ...v, otp_id: p?.id }))}
+                list={deviceList.map(e => ({
+                  description: e.device_description,
+                  id: e.otp_device_id
+                }))}
+              />
+
+            </FormProvider>
+
+            <div class="buttons is-right mt-5">
+              {onBack && (
+                <button class="button" onClick={onBack}>
+                  <i18n.Translate>Cancel</i18n.Translate>
+                </button>
+              )}
+              <AsyncButton
+                disabled={hasErrors}
+                data-tooltip={
+                  hasErrors
+                    ? i18n.str`Need to complete marked fields`
+                    : "confirm operation"
+                }
+                onClick={submitForm}
+              >
+                <i18n.Translate>Confirm</i18n.Translate>
+              </AsyncButton>
+            </div>
+          </div>
+          <div class="column" />
+        </div>
+      </section>
+    </div>
+  );
+}
diff --git 
a/packages/auditor-backoffice-ui/src/paths/instance/templates/create/index.tsx 
b/packages/auditor-backoffice-ui/src/paths/instance/templates/create/index.tsx
new file mode 100644
index 000000000..a29ee53b6
--- /dev/null
+++ 
b/packages/auditor-backoffice-ui/src/paths/instance/templates/create/index.tsx
@@ -0,0 +1,61 @@
+/*
+ This file is part of GNU Taler
+ (C) 2021-2023 Taler Systems S.A.
+
+ GNU Taler is free software; you can redistribute it and/or modify it under the
+ terms of the GNU General Public License as published by the Free Software
+ Foundation; either version 3, or (at your option) any later version.
+
+ GNU Taler is distributed in the hope that it will be useful, but WITHOUT ANY
+ WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
+ A PARTICULAR PURPOSE.  See the GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License along with
+ GNU Taler; see the file COPYING.  If not, see <http://www.gnu.org/licenses/>
+ */
+
+/**
+ *
+ * @author Sebastian Javier Marchano (sebasjm)
+ */
+
+import { useTranslationContext } from "@gnu-taler/web-util/browser";
+import { Fragment, h, VNode } from "preact";
+import { useState } from "preact/hooks";
+import { NotificationCard } from "../../../../components/menu/index.js";
+import { MerchantBackend } from "../../../../declaration.js";
+import { useTemplateAPI } from "../../../../hooks/templates.js";
+import { Notification } from "../../../../utils/types.js";
+import { CreatePage } from "./CreatePage.js";
+
+export type Entity = MerchantBackend.Transfers.TransferInformation;
+interface Props {
+  onBack?: () => void;
+  onConfirm: () => void;
+}
+
+export default function CreateTransfer({ onConfirm, onBack }: Props): VNode {
+  const { createTemplate } = useTemplateAPI();
+  const [notif, setNotif] = useState<Notification | undefined>(undefined);
+  const { i18n } = useTranslationContext();
+
+  return (
+    <>
+      <NotificationCard notification={notif} />
+      <CreatePage
+        onBack={onBack}
+        onCreate={(request: MerchantBackend.Template.TemplateAddDetails) => {
+          return createTemplate(request)
+            .then(() => onConfirm())
+            .catch((error) => {
+              setNotif({
+                message: i18n.str`could not inform template`,
+                type: "ERROR",
+                description: error.message,
+              });
+            });
+        }}
+      />
+    </>
+  );
+}
diff --git 
a/packages/auditor-backoffice-ui/src/paths/instance/templates/list/List.stories.tsx
 
b/packages/auditor-backoffice-ui/src/paths/instance/templates/list/List.stories.tsx
new file mode 100644
index 000000000..702e9ba4a
--- /dev/null
+++ 
b/packages/auditor-backoffice-ui/src/paths/instance/templates/list/List.stories.tsx
@@ -0,0 +1,28 @@
+/*
+ This file is part of GNU Taler
+ (C) 2021-2023 Taler Systems S.A.
+
+ GNU Taler is free software; you can redistribute it and/or modify it under the
+ terms of the GNU General Public License as published by the Free Software
+ Foundation; either version 3, or (at your option) any later version.
+
+ GNU Taler is distributed in the hope that it will be useful, but WITHOUT ANY
+ WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
+ A PARTICULAR PURPOSE.  See the GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License along with
+ GNU Taler; see the file COPYING.  If not, see <http://www.gnu.org/licenses/>
+ */
+
+/**
+ *
+ * @author Sebastian Javier Marchano (sebasjm)
+ */
+
+import { FunctionalComponent, h } from "preact";
+import { ListPage as TestedComponent } from "./ListPage.js";
+
+export default {
+  title: "Pages/Templates/List",
+  component: TestedComponent,
+};
diff --git 
a/packages/auditor-backoffice-ui/src/paths/instance/templates/list/ListPage.tsx 
b/packages/auditor-backoffice-ui/src/paths/instance/templates/list/ListPage.tsx
new file mode 100644
index 000000000..bf6062c34
--- /dev/null
+++ 
b/packages/auditor-backoffice-ui/src/paths/instance/templates/list/ListPage.tsx
@@ -0,0 +1,68 @@
+/*
+ This file is part of GNU Taler
+ (C) 2021-2023 Taler Systems S.A.
+
+ GNU Taler is free software; you can redistribute it and/or modify it under the
+ terms of the GNU General Public License as published by the Free Software
+ Foundation; either version 3, or (at your option) any later version.
+
+ GNU Taler is distributed in the hope that it will be useful, but WITHOUT ANY
+ WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
+ A PARTICULAR PURPOSE.  See the GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License along with
+ GNU Taler; see the file COPYING.  If not, see <http://www.gnu.org/licenses/>
+ */
+
+/**
+ *
+ * @author Sebastian Javier Marchano (sebasjm)
+ */
+
+import { h, VNode } from "preact";
+import { MerchantBackend } from "../../../../declaration.js";
+import { useTranslationContext } from "@gnu-taler/web-util/browser";
+import { CardTable } from "./Table.js";
+
+export interface Props {
+  templates: MerchantBackend.Template.TemplateEntry[];
+  onLoadMoreBefore?: () => void;
+  onLoadMoreAfter?: () => void;
+  onCreate: () => void;
+  onDelete: (e: MerchantBackend.Template.TemplateEntry) => void;
+  onSelect: (e: MerchantBackend.Template.TemplateEntry) => void;
+  onNewOrder: (e: MerchantBackend.Template.TemplateEntry) => void;
+  onQR: (e: MerchantBackend.Template.TemplateEntry) => void;
+}
+
+export function ListPage({
+  templates,
+  onCreate,
+  onDelete,
+  onSelect,
+  onNewOrder,
+  onQR,
+  onLoadMoreBefore,
+  onLoadMoreAfter,
+}: Props): VNode {
+  const form = { payto_uri: "" };
+
+  const { i18n } = useTranslationContext();
+  return (
+      <CardTable
+        templates={templates.map((o) => ({
+          ...o,
+          id: String(o.template_id),
+        }))}
+        onQR={onQR}
+        onCreate={onCreate}
+        onDelete={onDelete}
+        onSelect={onSelect}
+        onNewOrder={onNewOrder}
+        onLoadMoreBefore={onLoadMoreBefore}
+        hasMoreBefore={!onLoadMoreBefore}
+        onLoadMoreAfter={onLoadMoreAfter}
+        hasMoreAfter={!onLoadMoreAfter}
+      />
+  );
+}
diff --git 
a/packages/auditor-backoffice-ui/src/paths/instance/templates/list/Table.tsx 
b/packages/auditor-backoffice-ui/src/paths/instance/templates/list/Table.tsx
new file mode 100644
index 000000000..9fdf4ead9
--- /dev/null
+++ b/packages/auditor-backoffice-ui/src/paths/instance/templates/list/Table.tsx
@@ -0,0 +1,235 @@
+/*
+ This file is part of GNU Taler
+ (C) 2021-2023 Taler Systems S.A.
+
+ GNU Taler is free software; you can redistribute it and/or modify it under the
+ terms of the GNU General Public License as published by the Free Software
+ Foundation; either version 3, or (at your option) any later version.
+
+ GNU Taler is distributed in the hope that it will be useful, but WITHOUT ANY
+ WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
+ A PARTICULAR PURPOSE.  See the GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License along with
+ GNU Taler; see the file COPYING.  If not, see <http://www.gnu.org/licenses/>
+ */
+
+/**
+ *
+ * @author Sebastian Javier Marchano (sebasjm)
+ */
+
+import { useTranslationContext } from "@gnu-taler/web-util/browser";
+import { h, VNode } from "preact";
+import { StateUpdater, useState } from "preact/hooks";
+import { MerchantBackend } from "../../../../declaration.js";
+
+type Entity = MerchantBackend.Template.TemplateEntry;
+
+interface Props {
+  templates: Entity[];
+  onDelete: (e: Entity) => void;
+  onSelect: (e: Entity) => void;
+  onNewOrder: (e: Entity) => void;
+  onQR: (e: Entity) => void;
+  onCreate: () => void;
+  onLoadMoreBefore?: () => void;
+  hasMoreBefore?: boolean;
+  hasMoreAfter?: boolean;
+  onLoadMoreAfter?: () => void;
+}
+
+export function CardTable({
+  templates,
+  onCreate,
+  onDelete,
+  onSelect,
+  onQR,
+  onNewOrder,
+  onLoadMoreAfter,
+  onLoadMoreBefore,
+  hasMoreAfter,
+  hasMoreBefore,
+}: Props): VNode {
+  const [rowSelection, rowSelectionHandler] = useState<string[]>([]);
+
+  const { i18n } = useTranslationContext();
+
+  return (
+    <div class="card has-table">
+      <header class="card-header">
+        <p class="card-header-title">
+          <span class="icon">
+            <i class="mdi mdi-newspaper" />
+          </span>
+          <i18n.Translate>Templates</i18n.Translate>
+        </p>
+        <div class="card-header-icon" aria-label="more options">
+          <span
+            class="has-tooltip-left"
+            data-tooltip={i18n.str`add new templates`}
+          >
+            <button class="button is-info" type="button" onClick={onCreate}>
+              <span class="icon is-small">
+                <i class="mdi mdi-plus mdi-36px" />
+              </span>
+            </button>
+          </span>
+        </div>
+      </header>
+      <div class="card-content">
+        <div class="b-table has-pagination">
+          <div class="table-wrapper has-mobile-cards">
+            {templates.length > 0 ? (
+              <Table
+                instances={templates}
+                onDelete={onDelete}
+                onSelect={onSelect}
+                onNewOrder={onNewOrder}
+                onQR={onQR}
+                rowSelection={rowSelection}
+                rowSelectionHandler={rowSelectionHandler}
+                onLoadMoreAfter={onLoadMoreAfter}
+                onLoadMoreBefore={onLoadMoreBefore}
+                hasMoreAfter={hasMoreAfter}
+                hasMoreBefore={hasMoreBefore}
+              />
+            ) : (
+              <EmptyTable />
+            )}
+          </div>
+        </div>
+      </div>
+    </div>
+  );
+}
+interface TableProps {
+  rowSelection: string[];
+  instances: Entity[];
+  onDelete: (e: Entity) => void;
+  onNewOrder: (e: Entity) => void;
+  onQR: (e: Entity) => void;
+  onSelect: (e: Entity) => void;
+  rowSelectionHandler: StateUpdater<string[]>;
+  onLoadMoreBefore?: () => void;
+  hasMoreBefore?: boolean;
+  hasMoreAfter?: boolean;
+  onLoadMoreAfter?: () => void;
+}
+
+function toggleSelected<T>(id: T): (prev: T[]) => T[] {
+  return (prev: T[]): T[] =>
+    prev.indexOf(id) == -1 ? [...prev, id] : prev.filter((e) => e != id);
+}
+
+function Table({
+  instances,
+  onLoadMoreAfter,
+  onDelete,
+  onNewOrder,
+  onQR,
+  onSelect,
+  onLoadMoreBefore,
+  hasMoreAfter,
+  hasMoreBefore,
+}: TableProps): VNode {
+  const { i18n } = useTranslationContext();
+  return (
+    <div class="table-container">
+      {hasMoreBefore && (
+        <button
+          class="button is-fullwidth"
+          data-tooltip={i18n.str`load more templates before the first one`}
+          onClick={onLoadMoreBefore}
+        >
+          <i18n.Translate>load newer templates</i18n.Translate>
+        </button>
+      )}
+      <table class="table is-fullwidth is-striped is-hoverable is-fullwidth">
+        <thead>
+          <tr>
+            <th>
+              <i18n.Translate>ID</i18n.Translate>
+            </th>
+            <th>
+              <i18n.Translate>Description</i18n.Translate>
+            </th>
+            <th />
+          </tr>
+        </thead>
+        <tbody>
+          {instances.map((i) => {
+            return (
+              <tr key={i.template_id}>
+                <td
+                  onClick={(): void => onSelect(i)}
+                  style={{ cursor: "pointer" }}
+                >
+                  {i.template_id}
+                </td>
+                <td
+                  onClick={(): void => onSelect(i)}
+                  style={{ cursor: "pointer" }}
+                >
+                  {i.template_description}
+                </td>
+                <td class="is-actions-cell right-sticky">
+                  <div class="buttons is-right">
+                    <button
+                      class="button is-danger is-small has-tooltip-left"
+                      data-tooltip={i18n.str`delete selected templates from 
the database`}
+                      onClick={() => onDelete(i)}
+                    >
+                      Delete
+                    </button>
+                    <button
+                      class="button is-info is-small has-tooltip-left"
+                      data-tooltip={i18n.str`use template to create new order`}
+                      onClick={() => onNewOrder(i)}
+                    >
+                      Use template
+                    </button>
+                    <button
+                      class="button is-info is-small has-tooltip-left"
+                      data-tooltip={i18n.str`create qr code for the template`}
+                      onClick={() => onQR(i)}
+                    >
+                      QR
+                    </button>
+                  </div>
+                </td>
+              </tr>
+            );
+          })}
+        </tbody>
+      </table>
+      {hasMoreAfter && (
+        <button
+          class="button is-fullwidth"
+          data-tooltip={i18n.str`load more templates after the last one`}
+          onClick={onLoadMoreAfter}
+        >
+          <i18n.Translate>load older templates</i18n.Translate>
+        </button>
+      )}
+    </div>
+  );
+}
+
+function EmptyTable(): VNode {
+  const { i18n } = useTranslationContext();
+  return (
+    <div class="content has-text-grey has-text-centered">
+      <p>
+        <span class="icon is-large">
+          <i class="mdi mdi-emoticon-sad mdi-48px" />
+        </span>
+      </p>
+      <p>
+        <i18n.Translate>
+          There is no templates yet, add more pressing the + sign
+        </i18n.Translate>
+      </p>
+    </div>
+  );
+}
diff --git 
a/packages/auditor-backoffice-ui/src/paths/instance/templates/list/index.tsx 
b/packages/auditor-backoffice-ui/src/paths/instance/templates/list/index.tsx
new file mode 100644
index 000000000..b9767442f
--- /dev/null
+++ b/packages/auditor-backoffice-ui/src/paths/instance/templates/list/index.tsx
@@ -0,0 +1,152 @@
+/*
+ This file is part of GNU Taler
+ (C) 2021-2023 Taler Systems S.A.
+
+ GNU Taler is free software; you can redistribute it and/or modify it under the
+ terms of the GNU General Public License as published by the Free Software
+ Foundation; either version 3, or (at your option) any later version.
+
+ GNU Taler is distributed in the hope that it will be useful, but WITHOUT ANY
+ WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
+ A PARTICULAR PURPOSE.  See the GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License along with
+ GNU Taler; see the file COPYING.  If not, see <http://www.gnu.org/licenses/>
+ */
+
+/**
+ *
+ * @author Sebastian Javier Marchano (sebasjm)
+ */
+
+import {
+  ErrorType,
+  HttpError,
+  useTranslationContext,
+} from "@gnu-taler/web-util/browser";
+import { Fragment, h, VNode } from "preact";
+import { useState } from "preact/hooks";
+import { Loading } from "../../../../components/exception/loading.js";
+import { NotificationCard } from "../../../../components/menu/index.js";
+import { MerchantBackend } from "../../../../declaration.js";
+import {
+  useInstanceTemplates,
+  useTemplateAPI,
+} from "../../../../hooks/templates.js";
+import { Notification } from "../../../../utils/types.js";
+import { ListPage } from "./ListPage.js";
+import { HttpStatusCode, TranslatedString } from "@gnu-taler/taler-util";
+import { ConfirmModal } from "../../../../components/modal/index.js";
+import { JumpToElementById } from 
"../../../../components/form/JumpToElementById.js";
+
+interface Props {
+  onUnauthorized: () => VNode;
+  onLoadError: (error: HttpError<MerchantBackend.ErrorDetail>) => VNode;
+  onNotFound: () => VNode;
+  onCreate: () => void;
+  onSelect: (id: string) => void;
+  onNewOrder: (id: string) => void;
+  onQR: (id: string) => void;
+}
+
+export default function ListTemplates({
+  onUnauthorized,
+  onLoadError,
+  onCreate,
+  onQR,
+  onSelect,
+  onNewOrder,
+  onNotFound,
+}: Props): VNode {
+  const [position, setPosition] = useState<string | undefined>(undefined);
+  const { i18n } = useTranslationContext();
+  const [notif, setNotif] = useState<Notification | undefined>(undefined);
+  const { deleteTemplate, testTemplateExist } = useTemplateAPI();
+  const result = useInstanceTemplates({ position }, (id) => setPosition(id));
+  const [deleting, setDeleting] =
+    useState<MerchantBackend.Template.TemplateEntry | null>(null);
+
+  if (result.loading) return <Loading />;
+  if (!result.ok) {
+    if (
+      result.type === ErrorType.CLIENT &&
+      result.status === HttpStatusCode.Unauthorized
+    )
+      return onUnauthorized();
+    if (
+      result.type === ErrorType.CLIENT &&
+      result.status === HttpStatusCode.NotFound
+    )
+      return onNotFound();
+    return onLoadError(result);
+  }
+
+  return (
+    <section class="section is-main-section">
+      <NotificationCard notification={notif} />
+
+      <JumpToElementById
+        testIfExist={testTemplateExist} 
+        onSelect={onSelect}
+        description={i18n.str`jump to template with the given template ID`}
+        palceholder={i18n.str`template id`}
+      />
+
+      <ListPage
+        templates={result.data.templates}
+        onLoadMoreBefore={
+          result.isReachingStart ? result.loadMorePrev : undefined
+        }
+        onLoadMoreAfter={result.isReachingEnd ? result.loadMore : undefined}
+        onCreate={onCreate}
+        onSelect={(e) => {
+          onSelect(e.template_id);
+        }}
+        onNewOrder={(e) => {
+          onNewOrder(e.template_id);
+        }}
+        onQR={(e) => {
+          onQR(e.template_id);
+        }}
+        onDelete={(e: MerchantBackend.Template.TemplateEntry) => {
+          setDeleting(e)
+        }
+        }
+      />
+
+      {deleting && (
+        <ConfirmModal
+          label={`Delete template`}
+          description={`Delete the template 
"${deleting.template_description}"`}
+          danger
+          active
+          onCancel={() => setDeleting(null)}
+          onConfirm={async (): Promise<void> => {
+            try {
+              await deleteTemplate(deleting.template_id);
+              setNotif({
+                message: i18n.str`Template "${deleting.template_description}" 
(ID: ${deleting.template_id}) has been deleted`,
+                type: "SUCCESS",
+              });
+            } catch (error) {
+              setNotif({
+                message: i18n.str`Failed to delete template`,
+                type: "ERROR",
+                description: error instanceof Error ? error.message : 
undefined,
+              });
+            }
+            setDeleting(null);
+          }}
+        >
+          <p>
+            If you delete the template 
<b>&quot;{deleting.template_description}&quot;</b> (ID:{" "}
+            <b>{deleting.template_id}</b>) you may loose information
+          </p>
+          <p class="warning">
+            Deleting an template <b>cannot be undone</b>.
+          </p>
+        </ConfirmModal>
+      )}
+    </section>
+  );
+}
diff --git 
a/packages/auditor-backoffice-ui/src/paths/instance/templates/qr/Qr.stories.tsx 
b/packages/auditor-backoffice-ui/src/paths/instance/templates/qr/Qr.stories.tsx
new file mode 100644
index 000000000..eb853c8ff
--- /dev/null
+++ 
b/packages/auditor-backoffice-ui/src/paths/instance/templates/qr/Qr.stories.tsx
@@ -0,0 +1,27 @@
+/*
+ This file is part of GNU Taler
+ (C) 2021-2023 Taler Systems S.A.
+
+ GNU Taler is free software; you can redistribute it and/or modify it under the
+ terms of the GNU General Public License as published by the Free Software
+ Foundation; either version 3, or (at your option) any later version.
+
+ GNU Taler is distributed in the hope that it will be useful, but WITHOUT ANY
+ WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
+ A PARTICULAR PURPOSE.  See the GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License along with
+ GNU Taler; see the file COPYING.  If not, see <http://www.gnu.org/licenses/>
+ */
+
+/**
+ *
+ * @author Sebastian Javier Marchano (sebasjm)
+ */
+
+import { QrPage as TestedComponent } from "./QrPage.js";
+
+export default {
+  title: "Pages/Templates/QR",
+  component: TestedComponent,
+};
diff --git 
a/packages/auditor-backoffice-ui/src/paths/instance/templates/qr/QrPage.tsx 
b/packages/auditor-backoffice-ui/src/paths/instance/templates/qr/QrPage.tsx
new file mode 100644
index 000000000..5140aae3a
--- /dev/null
+++ b/packages/auditor-backoffice-ui/src/paths/instance/templates/qr/QrPage.tsx
@@ -0,0 +1,172 @@
+/*
+ This file is part of GNU Taler
+ (C) 2021-2023 Taler Systems S.A.
+
+ GNU Taler is free software; you can redistribute it and/or modify it under the
+ terms of the GNU General Public License as published by the Free Software
+ Foundation; either version 3, or (at your option) any later version.
+
+ GNU Taler is distributed in the hope that it will be useful, but WITHOUT ANY
+ WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
+ A PARTICULAR PURPOSE.  See the GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License along with
+ GNU Taler; see the file COPYING.  If not, see <http://www.gnu.org/licenses/>
+ */
+
+/**
+ *
+ * @author Sebastian Javier Marchano (sebasjm)
+ */
+
+import { stringifyPayTemplateUri } from "@gnu-taler/taler-util";
+import { useTranslationContext } from "@gnu-taler/web-util/browser";
+import { VNode, h } from "preact";
+import { useState } from "preact/hooks";
+import { QR } from "../../../../components/exception/QR.js";
+import {
+  FormErrors,
+  FormProvider,
+} from "../../../../components/form/FormProvider.js";
+import { Input } from "../../../../components/form/Input.js";
+import { InputCurrency } from "../../../../components/form/InputCurrency.js";
+import { useBackendContext } from "../../../../context/backend.js";
+import { useConfigContext } from "../../../../context/config.js";
+import { useInstanceContext } from "../../../../context/instance.js";
+import { MerchantBackend } from "../../../../declaration.js";
+
+type Entity = MerchantBackend.Template.UsingTemplateDetails;
+
+interface Props {
+  contract: MerchantBackend.Template.TemplateContractDetails;
+  id: string;
+  onBack?: () => void;
+}
+
+export function QrPage({ contract, id: templateId, onBack }: Props): VNode {
+  const { i18n } = useTranslationContext();
+  const { url: backendURL } = useBackendContext()
+  const { id: instanceId } = useInstanceContext();
+  const config = useConfigContext();
+
+  const [state, setState] = useState<Partial<Entity>>({
+    amount: contract.amount,
+    summary: contract.summary,
+  });
+
+  const errors: FormErrors<Entity> = {};
+
+  const fixedAmount = !!contract.amount;
+  const fixedSummary = !!contract.summary;
+
+  const templateParams: Record<string, string> = {}
+  if (!fixedAmount) {
+    if (state.amount) {
+      templateParams.amount = state.amount
+    } else {
+      templateParams.amount = config.currency
+    }
+  }
+
+  if (!fixedSummary) {
+    templateParams.summary = state.summary ?? ""
+  }
+
+  const merchantBaseUrl = new URL(backendURL).href;
+
+  const payTemplateUri = stringifyPayTemplateUri({
+    merchantBaseUrl,
+    templateId,
+    templateParams
+  })
+
+  const issuer = encodeURIComponent(
+    `${new URL(backendURL).host}/${instanceId}`,
+  );
+
+  return (
+    <div>
+      <section class="section is-main-section">
+        <div class="columns">
+          <div class="column" />
+          <div class="column is-four-fifths">
+            <p class="is-size-5 mt-5 mb-5">
+              <i18n.Translate>
+                Here you can specify a default value for fields that are not
+                fixed. Default values can be edited by the customer before the
+                payment.
+              </i18n.Translate>
+            </p>
+
+            <p></p>
+            <FormProvider
+              object={state}
+              valueHandler={setState}
+              errors={errors}
+            >
+              <InputCurrency<Entity>
+                name="amount"
+                label={
+                  fixedAmount
+                    ? i18n.str`Fixed amount`
+                    : i18n.str`Default amount`
+                }
+                readonly={fixedAmount}
+                tooltip={i18n.str`Amount of the order`}
+              />
+              <Input<Entity>
+                name="summary"
+                inputType="multiline"
+                readonly={fixedSummary}
+                label={
+                  fixedSummary
+                    ? i18n.str`Fixed summary`
+                    : i18n.str`Default summary`
+                }
+                tooltip={i18n.str`Title of the order to be shown to the 
customer`}
+              />
+            </FormProvider>
+
+            <div class="buttons is-right mt-5">
+              {onBack && (
+                <button class="button" onClick={onBack}>
+                  <i18n.Translate>Cancel</i18n.Translate>
+                </button>
+              )}
+              <button
+                class="button is-info"
+                onClick={() => saveAsPDF(templateId)}
+              >
+                <i18n.Translate>Print</i18n.Translate>
+              </button>
+            </div>
+          </div>
+          <div class="column" />
+        </div>
+      </section>
+      <section id="printThis">
+        <QR text={payTemplateUri} />
+        <pre style={{ textAlign: "center" }}>
+          <a href={payTemplateUri}>{payTemplateUri}</a>
+        </pre>
+      </section>
+    </div>
+  );
+}
+
+function saveAsPDF(name: string): void {
+  const printWindow = window.open("", "", "height=400,width=800");
+  if (!printWindow) return;
+  const divContents = document.getElementById("printThis");
+  if (!divContents) return;
+  printWindow.document.write(
+    `<html><head><title>Order template for ${name}</title><style>`,
+  );
+  printWindow.document.write("</style></head><body>&nbsp;</body></html>");
+  printWindow.document.close();
+  printWindow.document.body.appendChild(divContents.cloneNode(true));
+  printWindow.addEventListener("load", () => {
+    printWindow.print();
+    printWindow.close();
+  });
+}
diff --git 
a/packages/auditor-backoffice-ui/src/paths/instance/templates/qr/index.tsx 
b/packages/auditor-backoffice-ui/src/paths/instance/templates/qr/index.tsx
new file mode 100644
index 000000000..7db7478f7
--- /dev/null
+++ b/packages/auditor-backoffice-ui/src/paths/instance/templates/qr/index.tsx
@@ -0,0 +1,80 @@
+/*
+ This file is part of GNU Taler
+ (C) 2021-2023 Taler Systems S.A.
+
+ GNU Taler is free software; you can redistribute it and/or modify it under the
+ terms of the GNU General Public License as published by the Free Software
+ Foundation; either version 3, or (at your option) any later version.
+
+ GNU Taler is distributed in the hope that it will be useful, but WITHOUT ANY
+ WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
+ A PARTICULAR PURPOSE.  See the GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License along with
+ GNU Taler; see the file COPYING.  If not, see <http://www.gnu.org/licenses/>
+ */
+
+/**
+ *
+ * @author Sebastian Javier Marchano (sebasjm)
+ */
+
+import {
+  ErrorType,
+  HttpError,
+  useTranslationContext,
+} from "@gnu-taler/web-util/browser";
+import { Fragment, h, VNode } from "preact";
+import { useState } from "preact/hooks";
+import { Loading } from "../../../../components/exception/loading.js";
+import { NotificationCard } from "../../../../components/menu/index.js";
+import { MerchantBackend } from "../../../../declaration.js";
+import {
+  useTemplateAPI,
+  useTemplateDetails,
+} from "../../../../hooks/templates.js";
+import { Notification } from "../../../../utils/types.js";
+import { QrPage } from "./QrPage.js";
+import { HttpStatusCode } from "@gnu-taler/taler-util";
+
+export type Entity = MerchantBackend.Transfers.TransferInformation;
+interface Props {
+  onBack?: () => void;
+  onUnauthorized: () => VNode;
+  onNotFound: () => VNode;
+  onLoadError: (e: HttpError<MerchantBackend.ErrorDetail>) => VNode;
+  tid: string;
+}
+
+export default function TemplateQrPage({
+  tid,
+  onBack,
+  onLoadError,
+  onNotFound,
+  onUnauthorized,
+}: Props): VNode {
+  const result = useTemplateDetails(tid);
+  const [notif, setNotif] = useState<Notification | undefined>(undefined);
+
+  if (result.loading) return <Loading />;
+  if (!result.ok) {
+    if (
+      result.type === ErrorType.CLIENT &&
+      result.status === HttpStatusCode.Unauthorized
+    )
+      return onUnauthorized();
+    if (
+      result.type === ErrorType.CLIENT &&
+      result.status === HttpStatusCode.NotFound
+    )
+      return onNotFound();
+    return onLoadError(result);
+  }
+
+  return (
+    <>
+      <NotificationCard notification={notif} />
+      <QrPage contract={result.data.template_contract} id={tid} 
onBack={onBack} />
+    </>
+  );
+}
diff --git 
a/packages/auditor-backoffice-ui/src/paths/instance/templates/update/Update.stories.tsx
 
b/packages/auditor-backoffice-ui/src/paths/instance/templates/update/Update.stories.tsx
new file mode 100644
index 000000000..8d07cb31f
--- /dev/null
+++ 
b/packages/auditor-backoffice-ui/src/paths/instance/templates/update/Update.stories.tsx
@@ -0,0 +1,32 @@
+/*
+ This file is part of GNU Taler
+ (C) 2021-2023 Taler Systems S.A.
+
+ GNU Taler is free software; you can redistribute it and/or modify it under the
+ terms of the GNU General Public License as published by the Free Software
+ Foundation; either version 3, or (at your option) any later version.
+
+ GNU Taler is distributed in the hope that it will be useful, but WITHOUT ANY
+ WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
+ A PARTICULAR PURPOSE.  See the GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License along with
+ GNU Taler; see the file COPYING.  If not, see <http://www.gnu.org/licenses/>
+ */
+
+/**
+ *
+ * @author Sebastian Javier Marchano (sebasjm)
+ */
+
+import { h, VNode, FunctionalComponent } from "preact";
+import { UpdatePage as TestedComponent } from "./UpdatePage.js";
+
+export default {
+  title: "Pages/Templates/Update",
+  component: TestedComponent,
+  argTypes: {
+    onUpdate: { action: "onUpdate" },
+    onBack: { action: "onBack" },
+  },
+};
diff --git 
a/packages/auditor-backoffice-ui/src/paths/instance/templates/update/UpdatePage.tsx
 
b/packages/auditor-backoffice-ui/src/paths/instance/templates/update/UpdatePage.tsx
new file mode 100644
index 000000000..b578d4664
--- /dev/null
+++ 
b/packages/auditor-backoffice-ui/src/paths/instance/templates/update/UpdatePage.tsx
@@ -0,0 +1,254 @@
+/*
+ This file is part of GNU Taler
+ (C) 2021-2023 Taler Systems S.A.
+
+ GNU Taler is free software; you can redistribute it and/or modify it under the
+ terms of the GNU General Public License as published by the Free Software
+ Foundation; either version 3, or (at your option) any later version.
+
+ GNU Taler is distributed in the hope that it will be useful, but WITHOUT ANY
+ WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
+ A PARTICULAR PURPOSE.  See the GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License along with
+ GNU Taler; see the file COPYING.  If not, see <http://www.gnu.org/licenses/>
+ */
+
+/**
+ *
+ * @author Sebastian Javier Marchano (sebasjm)
+ */
+
+import {
+  Amounts,
+  MerchantTemplateContractDetails,
+} from "@gnu-taler/taler-util";
+import { useTranslationContext } from "@gnu-taler/web-util/browser";
+import { Fragment, VNode, h } from "preact";
+import { useState } from "preact/hooks";
+import { AsyncButton } from "../../../../components/exception/AsyncButton.js";
+import {
+  FormErrors,
+  FormProvider,
+} from "../../../../components/form/FormProvider.js";
+import { Input } from "../../../../components/form/Input.js";
+import { InputCurrency } from "../../../../components/form/InputCurrency.js";
+import { InputDuration } from "../../../../components/form/InputDuration.js";
+import { InputNumber } from "../../../../components/form/InputNumber.js";
+import { InputWithAddon } from "../../../../components/form/InputWithAddon.js";
+import { useBackendContext } from "../../../../context/backend.js";
+import { MerchantBackend, WithId } from "../../../../declaration.js";
+import { undefinedIfEmpty } from "../../../../utils/table.js";
+import { InputTab } from "../../../../components/form/InputTab.js";
+
+enum Steps {
+  BOTH_FIXED,
+  FIXED_PRICE,
+  FIXED_SUMMARY,
+  NON_FIXED,
+}
+
+type Entity = MerchantBackend.Template.TemplatePatchDetails & WithId;
+
+interface Props {
+  onUpdate: (d: Entity) => Promise<void>;
+  onBack?: () => void;
+  template: Entity;
+}
+
+export function UpdatePage({ template, onUpdate, onBack }: Props): VNode {
+  const { i18n } = useTranslationContext();
+  const { url: backendURL } = useBackendContext()
+
+  const intialStep =
+    template.template_contract?.amount === undefined && 
template.template_contract?.summary === undefined
+      ? Steps.NON_FIXED
+      : template.template_contract?.summary === undefined
+        ? Steps.FIXED_PRICE
+        : template.template_contract?.amount === undefined
+          ? Steps.FIXED_SUMMARY
+          : Steps.BOTH_FIXED;
+
+  const [state, setState] = useState<Partial<Entity & { type: Steps }>>({ 
...template, type: intialStep });
+
+  const parsedPrice = !state.template_contract?.amount
+    ? undefined
+    : Amounts.parse(state.template_contract?.amount);
+
+  const errors: FormErrors<Entity> = {
+    template_description: !state.template_description
+      ? i18n.str`should not be empty`
+      : undefined,
+    template_contract: !state.template_contract
+      ? undefined
+      : undefinedIfEmpty({
+        amount: !(state.type === Steps.FIXED_PRICE || state.type === 
Steps.BOTH_FIXED)
+          ? undefined
+          : !state.template_contract?.amount
+            ? i18n.str`required`
+            : !parsedPrice
+              ? i18n.str`not valid`
+              : Amounts.isZero(parsedPrice)
+                ? i18n.str`must be greater than 0`
+                : undefined,
+        summary: !(state.type === Steps.FIXED_SUMMARY || state.type === 
Steps.BOTH_FIXED)
+          ? undefined
+          : !state.template_contract?.summary
+            ? i18n.str`required`
+            : undefined,
+        minimum_age:
+          state.template_contract.minimum_age < 0
+            ? i18n.str`should be greater that 0`
+            : undefined,
+        pay_duration: !state.template_contract.pay_duration
+          ? i18n.str`can't be empty`
+          : state.template_contract.pay_duration.d_us === "forever"
+            ? undefined
+            : state.template_contract.pay_duration.d_us < 1000 * 1000 // less 
than one second
+              ? i18n.str`to short`
+              : undefined,
+      } as Partial<MerchantTemplateContractDetails>),
+  };
+
+  const hasErrors = Object.keys(errors).some(
+    (k) => (errors as any)[k] !== undefined,
+  );
+
+  const submitForm = () => {
+    if (hasErrors) return Promise.reject();
+    if (state.template_contract) {
+      if (state.type === Steps.NON_FIXED) {
+        delete state.template_contract.amount;
+        delete state.template_contract.summary;
+      } else if (state.type === Steps.FIXED_SUMMARY) {
+        delete state.template_contract.amount;
+      } else if (state.type === Steps.FIXED_PRICE) {
+        delete state.template_contract.summary;
+      }
+    }
+    delete state.type
+    return onUpdate(state as any);
+  };
+
+
+  return (
+    <div>
+      <section class="section">
+        <section class="hero is-hero-bar">
+          <div class="hero-body">
+            <div class="level">
+              <div class="level-left">
+                <div class="level-item">
+                  <span class="is-size-4">
+                    {backendURL}/templates/{template.id}
+                  </span>
+                </div>
+              </div>
+            </div>
+          </div>
+        </section>
+        <hr />
+
+        <section class="section is-main-section">
+          <div class="columns">
+            <div class="column is-four-fifths">
+              <FormProvider
+                object={state}
+                valueHandler={setState}
+                errors={errors}
+              >
+                <InputWithAddon<Entity>
+                  name="id"
+                  addonBefore={`templates/`}
+                  readonly
+                  label={i18n.str`Identifier`}
+                  tooltip={i18n.str`Name of the template in URLs.`}
+                />
+
+                <Input<Entity>
+                  name="template_description"
+                  label={i18n.str`Description`}
+                  help=""
+                  tooltip={i18n.str`Describe what this template stands for`}
+                />
+                <InputTab
+                  name="type"
+                  label={i18n.str`Type`}
+                  help={(() => {
+                    switch (state.type) {
+                      case Steps.NON_FIXED: return i18n.str`User will be able 
to input price and summary before payment.`
+                      case Steps.FIXED_PRICE: return i18n.str`User will be 
able to add a summary before payment.`
+                      case Steps.FIXED_SUMMARY: return i18n.str`User will be 
able to set the price before payment.`
+                      case Steps.BOTH_FIXED: return i18n.str`User will not be 
able to change the price or the summary.`
+                    }
+                  })()}
+                  tooltip={i18n.str`Define what the user be allowed to modify`}
+                  values={[
+                    Steps.NON_FIXED,
+                    Steps.FIXED_PRICE,
+                    Steps.FIXED_SUMMARY,
+                    Steps.BOTH_FIXED,
+                  ]}
+                  toStr={(v: Steps): string => {
+                    switch (v) {
+                      case Steps.NON_FIXED: return i18n.str`Simple`
+                      case Steps.FIXED_PRICE: return i18n.str`With price`
+                      case Steps.FIXED_SUMMARY: return i18n.str`With summary`
+                      case Steps.BOTH_FIXED: return i18n.str`With price and 
summary`
+                    }
+                  }}
+                />
+                {state.type === Steps.BOTH_FIXED || state.type === 
Steps.FIXED_SUMMARY ?
+                  <Input
+                    name="template_contract.summary"
+                    inputType="multiline"
+                    label={i18n.str`Fixed summary`}
+                    tooltip={i18n.str`If specified, this template will create 
order with the same summary`}
+                  />
+                  : undefined}
+                {state.type === Steps.BOTH_FIXED || state.type === 
Steps.FIXED_PRICE ?
+                  <InputCurrency
+                    name="template_contract.amount"
+                    label={i18n.str`Fixed price`}
+                    tooltip={i18n.str`If specified, this template will create 
order with the same price`}
+                  />
+                  : undefined}
+                <InputNumber
+                  name="template_contract.minimum_age"
+                  label={i18n.str`Minimum age`}
+                  help=""
+                  tooltip={i18n.str`Is this contract restricted to some age?`}
+                />
+                <InputDuration
+                  name="template_contract.pay_duration"
+                  label={i18n.str`Payment timeout`}
+                  help=""
+                  tooltip={i18n.str`How much time has the customer to complete 
the payment once the order was created.`}
+                />
+              </FormProvider>
+
+              <div class="buttons is-right mt-5">
+                {onBack && (
+                  <button class="button" onClick={onBack}>
+                    <i18n.Translate>Cancel</i18n.Translate>
+                  </button>
+                )}
+                <AsyncButton
+                  disabled={hasErrors}
+                  data-tooltip={
+                    hasErrors
+                      ? i18n.str`Need to complete marked fields`
+                      : "confirm operation"
+                  }
+                  onClick={submitForm}
+                >
+                  <i18n.Translate>Confirm</i18n.Translate>
+                </AsyncButton>
+              </div>
+            </div>
+          </div>
+        </section>
+      </section>
+    </div>
+  );
+}
diff --git 
a/packages/auditor-backoffice-ui/src/paths/instance/templates/update/index.tsx 
b/packages/auditor-backoffice-ui/src/paths/instance/templates/update/index.tsx
new file mode 100644
index 000000000..3adca45db
--- /dev/null
+++ 
b/packages/auditor-backoffice-ui/src/paths/instance/templates/update/index.tsx
@@ -0,0 +1,99 @@
+/*
+ This file is part of GNU Taler
+ (C) 2021-2023 Taler Systems S.A.
+
+ GNU Taler is free software; you can redistribute it and/or modify it under the
+ terms of the GNU General Public License as published by the Free Software
+ Foundation; either version 3, or (at your option) any later version.
+
+ GNU Taler is distributed in the hope that it will be useful, but WITHOUT ANY
+ WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
+ A PARTICULAR PURPOSE.  See the GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License along with
+ GNU Taler; see the file COPYING.  If not, see <http://www.gnu.org/licenses/>
+ */
+
+/**
+ *
+ * @author Sebastian Javier Marchano (sebasjm)
+ */
+
+import {
+  ErrorType,
+  HttpError,
+  useTranslationContext,
+} from "@gnu-taler/web-util/browser";
+import { Fragment, h, VNode } from "preact";
+import { useState } from "preact/hooks";
+import { Loading } from "../../../../components/exception/loading.js";
+import { NotificationCard } from "../../../../components/menu/index.js";
+import { MerchantBackend, WithId } from "../../../../declaration.js";
+import {
+  useTemplateAPI,
+  useTemplateDetails,
+} from "../../../../hooks/templates.js";
+import { Notification } from "../../../../utils/types.js";
+import { UpdatePage } from "./UpdatePage.js";
+import { HttpStatusCode } from "@gnu-taler/taler-util";
+
+export type Entity = MerchantBackend.Template.TemplatePatchDetails & WithId;
+
+interface Props {
+  onBack?: () => void;
+  onConfirm: () => void;
+  onUnauthorized: () => VNode;
+  onNotFound: () => VNode;
+  onLoadError: (e: HttpError<MerchantBackend.ErrorDetail>) => VNode;
+  tid: string;
+}
+export default function UpdateTemplate({
+  tid,
+  onConfirm,
+  onBack,
+  onUnauthorized,
+  onNotFound,
+  onLoadError,
+}: Props): VNode {
+  const { updateTemplate } = useTemplateAPI();
+  const result = useTemplateDetails(tid);
+  const [notif, setNotif] = useState<Notification | undefined>(undefined);
+
+  const { i18n } = useTranslationContext();
+
+  if (result.loading) return <Loading />;
+  if (!result.ok) {
+    if (
+      result.type === ErrorType.CLIENT &&
+      result.status === HttpStatusCode.Unauthorized
+    )
+      return onUnauthorized();
+    if (
+      result.type === ErrorType.CLIENT &&
+      result.status === HttpStatusCode.NotFound
+    )
+      return onNotFound();
+    return onLoadError(result);
+  }
+
+  return (
+    <Fragment>
+      <NotificationCard notification={notif} />
+      <UpdatePage
+        template={{ ...result.data, id: tid }}
+        onBack={onBack}
+        onUpdate={(data) => {
+          return updateTemplate(tid, data)
+            .then(onConfirm)
+            .catch((error) => {
+              setNotif({
+                message: i18n.str`could not update template`,
+                type: "ERROR",
+                description: error.message,
+              });
+            });
+        }}
+      />
+    </Fragment>
+  );
+}
diff --git 
a/packages/auditor-backoffice-ui/src/paths/instance/templates/use/Use.stories.tsx
 
b/packages/auditor-backoffice-ui/src/paths/instance/templates/use/Use.stories.tsx
new file mode 100644
index 000000000..13576d94d
--- /dev/null
+++ 
b/packages/auditor-backoffice-ui/src/paths/instance/templates/use/Use.stories.tsx
@@ -0,0 +1,27 @@
+/*
+ This file is part of GNU Taler
+ (C) 2021-2023 Taler Systems S.A.
+
+ GNU Taler is free software; you can redistribute it and/or modify it under the
+ terms of the GNU General Public License as published by the Free Software
+ Foundation; either version 3, or (at your option) any later version.
+
+ GNU Taler is distributed in the hope that it will be useful, but WITHOUT ANY
+ WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
+ A PARTICULAR PURPOSE.  See the GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License along with
+ GNU Taler; see the file COPYING.  If not, see <http://www.gnu.org/licenses/>
+ */
+
+/**
+ *
+ * @author Sebastian Javier Marchano (sebasjm)
+ */
+
+import { UsePage as TestedComponent } from "./UsePage.js";
+
+export default {
+  title: "Pages/Templates/Create",
+  component: TestedComponent,
+};
diff --git 
a/packages/auditor-backoffice-ui/src/paths/instance/templates/use/UsePage.tsx 
b/packages/auditor-backoffice-ui/src/paths/instance/templates/use/UsePage.tsx
new file mode 100644
index 000000000..983804d3e
--- /dev/null
+++ 
b/packages/auditor-backoffice-ui/src/paths/instance/templates/use/UsePage.tsx
@@ -0,0 +1,143 @@
+/*
+ This file is part of GNU Taler
+ (C) 2021-2023 Taler Systems S.A.
+
+ GNU Taler is free software; you can redistribute it and/or modify it under the
+ terms of the GNU General Public License as published by the Free Software
+ Foundation; either version 3, or (at your option) any later version.
+
+ GNU Taler is distributed in the hope that it will be useful, but WITHOUT ANY
+ WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
+ A PARTICULAR PURPOSE.  See the GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License along with
+ GNU Taler; see the file COPYING.  If not, see <http://www.gnu.org/licenses/>
+ */
+
+/**
+ *
+ * @author Sebastian Javier Marchano (sebasjm)
+ */
+
+import { useTranslationContext } from "@gnu-taler/web-util/browser";
+import { h, VNode } from "preact";
+import { useState } from "preact/hooks";
+import { AsyncButton } from "../../../../components/exception/AsyncButton.js";
+import {
+  FormErrors,
+  FormProvider,
+} from "../../../../components/form/FormProvider.js";
+import { Input } from "../../../../components/form/Input.js";
+import { InputCurrency } from "../../../../components/form/InputCurrency.js";
+import { MerchantBackend } from "../../../../declaration.js";
+
+type Entity = MerchantBackend.Template.UsingTemplateDetails;
+
+interface Props {
+  id: string;
+  template: MerchantBackend.Template.TemplateDetails;
+  onCreateOrder: (d: Entity) => Promise<void>;
+  onBack?: () => void;
+}
+
+export function UsePage({ id, template, onCreateOrder, onBack }: Props): VNode 
{
+  const { i18n } = useTranslationContext();
+
+  const [state, setState] = useState<Partial<Entity>>({
+    amount: template.template_contract.amount,
+    summary: template.template_contract.summary,
+  });
+
+  const errors: FormErrors<Entity> = {
+    amount:
+      !template.template_contract.amount && !state.amount
+        ? i18n.str`Amount is required`
+        : undefined,
+    summary:
+      !template.template_contract.summary && !state.summary
+        ? i18n.str`Order summary is required`
+        : undefined,
+  };
+
+  const hasErrors = Object.keys(errors).some(
+    (k) => (errors as any)[k] !== undefined,
+  );
+
+  const submitForm = () => {
+    if (hasErrors) return Promise.reject();
+    if (template.template_contract.amount) {
+      delete state.amount;
+    }
+    if (template.template_contract.summary) {
+      delete state.summary;
+    }
+    return onCreateOrder(state as any);
+  };
+
+  return (
+    <div>
+      <section class="section">
+        <section class="hero is-hero-bar">
+          <div class="hero-body">
+            <div class="level">
+              <div class="level-left">
+                <div class="level-item">
+                  <span class="is-size-4">
+                    <i18n.Translate>New order for template</i18n.Translate>:{" 
"}
+                    <b>{id}</b>
+                  </span>
+                </div>
+              </div>
+            </div>
+          </div>
+        </section>
+      </section>
+      <section class="section is-main-section">
+        <div class="columns">
+          <div class="column" />
+          <div class="column is-four-fifths">
+            <FormProvider
+              object={state}
+              valueHandler={setState}
+              errors={errors}
+            >
+              <InputCurrency<Entity>
+                name="amount"
+                label={i18n.str`Amount`}
+                readonly={!!template.template_contract.amount}
+                tooltip={i18n.str`Amount of the order`}
+              />
+              <Input<Entity>
+                name="summary"
+                inputType="multiline"
+                label={i18n.str`Order summary`}
+                readonly={!!template.template_contract.summary}
+                tooltip={i18n.str`Title of the order to be shown to the 
customer`}
+              />
+            </FormProvider>
+
+            <div class="buttons is-right mt-5">
+              {onBack && (
+                <button class="button" onClick={onBack}>
+                  <i18n.Translate>Cancel</i18n.Translate>
+                </button>
+              )}
+              <AsyncButton
+                disabled={hasErrors}
+                data-tooltip={
+                  hasErrors
+                    ? i18n.str`Need to complete marked fields`
+                    : "confirm operation"
+                }
+                onClick={submitForm}
+              >
+                <i18n.Translate>Confirm</i18n.Translate>
+              </AsyncButton>
+            </div>
+          </div>
+          <div class="column" />
+        </div>
+      </section>
+    </div>
+  );
+}
diff --git 
a/packages/auditor-backoffice-ui/src/paths/instance/templates/use/index.tsx 
b/packages/auditor-backoffice-ui/src/paths/instance/templates/use/index.tsx
new file mode 100644
index 000000000..ed1242ef5
--- /dev/null
+++ b/packages/auditor-backoffice-ui/src/paths/instance/templates/use/index.tsx
@@ -0,0 +1,101 @@
+/*
+ This file is part of GNU Taler
+ (C) 2021-2023 Taler Systems S.A.
+
+ GNU Taler is free software; you can redistribute it and/or modify it under the
+ terms of the GNU General Public License as published by the Free Software
+ Foundation; either version 3, or (at your option) any later version.
+
+ GNU Taler is distributed in the hope that it will be useful, but WITHOUT ANY
+ WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
+ A PARTICULAR PURPOSE.  See the GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License along with
+ GNU Taler; see the file COPYING.  If not, see <http://www.gnu.org/licenses/>
+ */
+
+/**
+ *
+ * @author Sebastian Javier Marchano (sebasjm)
+ */
+
+import {
+  ErrorType,
+  HttpError,
+  useTranslationContext,
+} from "@gnu-taler/web-util/browser";
+import { Fragment, h, VNode } from "preact";
+import { useState } from "preact/hooks";
+import { Loading } from "../../../../components/exception/loading.js";
+import { NotificationCard } from "../../../../components/menu/index.js";
+import { MerchantBackend } from "../../../../declaration.js";
+import {
+  useTemplateAPI,
+  useTemplateDetails,
+} from "../../../../hooks/templates.js";
+import { Notification } from "../../../../utils/types.js";
+import { UsePage } from "./UsePage.js";
+import { HttpStatusCode } from "@gnu-taler/taler-util";
+
+export type Entity = MerchantBackend.Transfers.TransferInformation;
+interface Props {
+  onBack?: () => void;
+  onOrderCreated: (id: string) => void;
+  onUnauthorized: () => VNode;
+  onNotFound: () => VNode;
+  onLoadError: (e: HttpError<MerchantBackend.ErrorDetail>) => VNode;
+  tid: string;
+}
+
+export default function TemplateUsePage({
+  tid,
+  onOrderCreated,
+  onBack,
+  onLoadError,
+  onNotFound,
+  onUnauthorized,
+}: Props): VNode {
+  const { createOrderFromTemplate } = useTemplateAPI();
+  const result = useTemplateDetails(tid);
+  const [notif, setNotif] = useState<Notification | undefined>(undefined);
+  const { i18n } = useTranslationContext();
+
+  if (result.loading) return <Loading />;
+  if (!result.ok) {
+    if (
+      result.type === ErrorType.CLIENT &&
+      result.status === HttpStatusCode.Unauthorized
+    )
+      return onUnauthorized();
+    if (
+      result.type === ErrorType.CLIENT &&
+      result.status === HttpStatusCode.NotFound
+    )
+      return onNotFound();
+    return onLoadError(result);
+  }
+
+  return (
+    <>
+      <NotificationCard notification={notif} />
+      <UsePage
+        template={result.data}
+        id={tid}
+        onBack={onBack}
+        onCreateOrder={(
+          request: MerchantBackend.Template.UsingTemplateDetails,
+        ) => {
+          return createOrderFromTemplate(tid, request)
+            .then((res) => onOrderCreated(res.data.order_id))
+            .catch((error) => {
+              setNotif({
+                message: i18n.str`could not create order from template`,
+                type: "ERROR",
+                description: error.message,
+              });
+            });
+        }}
+      />
+    </>
+  );
+}
diff --git 
a/packages/auditor-backoffice-ui/src/paths/instance/token/DetailPage.tsx 
b/packages/auditor-backoffice-ui/src/paths/instance/token/DetailPage.tsx
new file mode 100644
index 000000000..d22a9e4d4
--- /dev/null
+++ b/packages/auditor-backoffice-ui/src/paths/instance/token/DetailPage.tsx
@@ -0,0 +1,183 @@
+/*
+ This file is part of GNU Taler
+ (C) 2021-2023 Taler Systems S.A.
+
+ GNU Taler is free software; you can redistribute it and/or modify it under the
+ terms of the GNU General Public License as published by the Free Software
+ Foundation; either version 3, or (at your option) any later version.
+
+ GNU Taler is distributed in the hope that it will be useful, but WITHOUT ANY
+ WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
+ A PARTICULAR PURPOSE.  See the GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License along with
+ GNU Taler; see the file COPYING.  If not, see <http://www.gnu.org/licenses/>
+ */
+
+/**
+ *
+ * @author Sebastian Javier Marchano (sebasjm)
+ */
+
+import { useTranslationContext } from "@gnu-taler/web-util/browser";
+import { Fragment, h, VNode } from "preact";
+import { useState } from "preact/hooks";
+import { AsyncButton } from "../../../components/exception/AsyncButton.js";
+import { FormProvider } from "../../../components/form/FormProvider.js";
+import { Input } from "../../../components/form/Input.js";
+import { useInstanceContext } from "../../../context/instance.js";
+import { AccessToken } from "../../../declaration.js";
+import { NotificationCard } from "../../../components/menu/index.js";
+
+interface Props {
+  instanceId: string;
+  hasToken: boolean | undefined;
+  onClearToken: (c: AccessToken | undefined) => void;
+  onNewToken: (c: AccessToken | undefined, s: AccessToken) => void;
+  onBack?: () => void;
+}
+
+export function DetailPage({ instanceId, hasToken, onBack, onNewToken, 
onClearToken }: Props): VNode {
+  type State = { old_token: string; new_token: string; repeat_token: string };
+  const [form, setValue] = useState<Partial<State>>({
+    old_token: "",
+    new_token: "",
+    repeat_token: "",
+  });
+  const { i18n } = useTranslationContext();
+
+  const errors = {
+    old_token: hasToken && !form.old_token
+      ? i18n.str`you need your access token to perform the operation`
+      : undefined,
+    new_token: !form.new_token
+      ? i18n.str`cannot be empty`
+      : form.new_token === form.old_token
+        ? i18n.str`cannot be the same as the old token`
+        : undefined,
+    repeat_token:
+      form.new_token !== form.repeat_token
+        ? i18n.str`is not the same`
+        : undefined,
+  };
+
+  const hasErrors = Object.keys(errors).some(
+    (k) => (errors as any)[k] !== undefined,
+  );
+
+  const instance = useInstanceContext();
+
+  const text = i18n.str`You are updating the access token from instance with 
id "${instance.id}"`;
+
+  async function submitForm() {
+    if (hasErrors) return;
+    const ot = hasToken ? `secret-token:${form.old_token}` as AccessToken : 
undefined;
+    const nt = `secret-token:${form.new_token}` as AccessToken;
+    onNewToken(ot, nt)
+  }
+
+  return (
+    <div>
+      <section class="section">
+        <section class="hero is-hero-bar">
+          <div class="hero-body">
+            <div class="level">
+              <div class="level-left">
+                <div class="level-item">
+                  <span class="is-size-4">
+                    {text}
+                  </span>
+                </div>
+              </div>
+            </div>
+          </div>
+        </section>
+        <hr />
+        
+        {!hasToken &&
+          <NotificationCard
+            notification={{
+              message: i18n.str`This instance doesn't have authentication 
token.`,
+              description: i18n.str`You can leave it empty if there is another 
layer of security.`,
+              type: "WARN",
+            }}
+          />
+        }
+
+        <div class="columns">
+          <div class="column" />
+          <div class="column is-four-fifths">
+            <FormProvider errors={errors} object={form} 
valueHandler={setValue}>
+              <Fragment>
+                {hasToken && (
+                  <Fragment>
+                    <Input<State>
+                      name="old_token"
+                      label={i18n.str`Current access token`}
+                      tooltip={i18n.str`access token currently in use`}
+                      inputType="password"
+                    />
+                    <p>
+                      <i18n.Translate>
+                        Clearing the access token will mean public access to 
the instance.
+                      </i18n.Translate>
+                    </p>
+                    <div class="buttons is-right mt-5">
+                      <button
+                        class="button"
+                        onClick={() => {
+                          if (hasToken) {
+                            const ot = `secret-token:${form.old_token}` as 
AccessToken;
+                            onClearToken(ot)
+                          } else {
+                            onClearToken(undefined)
+                          }
+                        }}
+                      >
+                        <i18n.Translate>Clear token</i18n.Translate>
+                      </button>
+                    </div>
+                  </Fragment>
+                )}
+
+
+                <Input<State>
+                  name="new_token"
+                  label={i18n.str`New access token`}
+                  tooltip={i18n.str`next access token to be used`}
+                  inputType="password"
+                />
+                <Input<State>
+                  name="repeat_token"
+                  label={i18n.str`Repeat access token`}
+                  tooltip={i18n.str`confirm the same access token`}
+                  inputType="password"
+                />
+              </Fragment>
+            </FormProvider>
+            <div class="buttons is-right mt-5">
+              {onBack && (
+                <button class="button" onClick={onBack}>
+                  <i18n.Translate>Cancel</i18n.Translate>
+                </button>
+              )}
+              <AsyncButton
+                disabled={hasErrors}
+                data-tooltip={
+                  hasErrors
+                    ? i18n.str`Need to complete marked fields`
+                    : "confirm operation"
+                }
+                onClick={submitForm}
+              >
+                <i18n.Translate>Confirm change</i18n.Translate>
+              </AsyncButton>
+            </div>
+          </div>
+          <div class="column" />
+        </div>
+
+      </section>
+    </div>
+  );
+}
diff --git a/packages/auditor-backoffice-ui/src/paths/instance/token/index.tsx 
b/packages/auditor-backoffice-ui/src/paths/instance/token/index.tsx
new file mode 100644
index 000000000..22365c9e1
--- /dev/null
+++ b/packages/auditor-backoffice-ui/src/paths/instance/token/index.tsx
@@ -0,0 +1,106 @@
+/*
+ This file is part of GNU Taler
+ (C) 2021-2023 Taler Systems S.A.
+
+ GNU Taler is free software; you can redistribute it and/or modify it under the
+ terms of the GNU General Public License as published by the Free Software
+ Foundation; either version 3, or (at your option) any later version.
+
+ GNU Taler is distributed in the hope that it will be useful, but WITHOUT ANY
+ WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
+ A PARTICULAR PURPOSE.  See the GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License along with
+ GNU Taler; see the file COPYING.  If not, see <http://www.gnu.org/licenses/>
+ */
+import { HttpStatusCode } from "@gnu-taler/taler-util";
+import { ErrorType, HttpError, useTranslationContext } from 
"@gnu-taler/web-util/browser";
+import { Fragment, VNode, h } from "preact";
+import { Loading } from "../../../components/exception/loading.js";
+import { AccessToken, MerchantBackend } from "../../../declaration.js";
+import { useInstanceAPI, useInstanceDetails } from 
"../../../hooks/instance.js";
+import { DetailPage } from "./DetailPage.js";
+import { useInstanceContext } from "../../../context/instance.js";
+import { useState } from "preact/hooks";
+import { NotificationCard } from "../../../components/menu/index.js";
+import { Notification } from "../../../utils/types.js";
+import { useBackendContext } from "../../../context/backend.js";
+
+interface Props {
+  onUnauthorized: () => VNode;
+  onLoadError: (error: HttpError<MerchantBackend.ErrorDetail>) => VNode;
+  onChange: () => void;
+  onNotFound: () => VNode;
+  onCancel: () => void;
+}
+
+export default function Token({
+  onLoadError,
+  onChange,
+  onUnauthorized,
+  onNotFound,
+  onCancel,
+}: Props): VNode {
+  const { i18n } = useTranslationContext();
+
+  const [notif, setNotif] = useState<Notification | undefined>(undefined);
+  const { clearAccessToken, setNewAccessToken } = useInstanceAPI();
+  const { id } = useInstanceContext();
+  const result = useInstanceDetails()
+
+  if (result.loading) return <Loading />;
+  if (!result.ok) {
+    if (
+      result.type === ErrorType.CLIENT &&
+      result.status === HttpStatusCode.Unauthorized
+    )
+      return onUnauthorized();
+    if (
+      result.type === ErrorType.CLIENT &&
+      result.status === HttpStatusCode.NotFound
+    )
+      return onNotFound();
+    return onLoadError(result);
+  }
+
+  const hasToken = result.data.auth.method === "token"
+
+  return (
+    <Fragment>
+      <NotificationCard notification={notif} />
+      <DetailPage
+        instanceId={id}
+        onBack={onCancel}
+        hasToken={hasToken}
+        onClearToken={async (currentToken): Promise<void> => {
+          try {
+            await clearAccessToken(currentToken);
+            onChange();
+          } catch (error) {
+            if (error instanceof Error) {
+              setNotif({
+                message: i18n.str`Failed to clear token`,
+                type: "ERROR",
+                description: error.message,
+              });
+            }
+          }
+        }}
+        onNewToken={async (currentToken, newToken): Promise<void> => {
+          try {
+            await setNewAccessToken(currentToken, newToken);
+            onChange();
+          } catch (error) {
+            if (error instanceof Error) {
+              setNotif({
+                message: i18n.str`Failed to set new token`,
+                type: "ERROR",
+                description: error.message,
+              });
+            }
+          }
+        }}
+      />
+    </Fragment>
+  );
+}
diff --git 
a/packages/auditor-backoffice-ui/src/paths/instance/token/stories.tsx 
b/packages/auditor-backoffice-ui/src/paths/instance/token/stories.tsx
new file mode 100644
index 000000000..5f0f56f2d
--- /dev/null
+++ b/packages/auditor-backoffice-ui/src/paths/instance/token/stories.tsx
@@ -0,0 +1,28 @@
+/*
+ This file is part of GNU Taler
+ (C) 2021-2023 Taler Systems S.A.
+
+ GNU Taler is free software; you can redistribute it and/or modify it under the
+ terms of the GNU General Public License as published by the Free Software
+ Foundation; either version 3, or (at your option) any later version.
+
+ GNU Taler is distributed in the hope that it will be useful, but WITHOUT ANY
+ WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
+ A PARTICULAR PURPOSE.  See the GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License along with
+ GNU Taler; see the file COPYING.  If not, see <http://www.gnu.org/licenses/>
+ */
+
+/**
+ *
+ * @author Sebastian Javier Marchano (sebasjm)
+ */
+
+import { DetailPage as TestedComponent } from "./DetailPage.js";
+
+export default {
+  title: "Pages/Token",
+  component: TestedComponent,
+};
+
diff --git 
a/packages/auditor-backoffice-ui/src/paths/instance/transfers/create/Create.stories.tsx
 
b/packages/auditor-backoffice-ui/src/paths/instance/transfers/create/Create.stories.tsx
new file mode 100644
index 000000000..64b67335c
--- /dev/null
+++ 
b/packages/auditor-backoffice-ui/src/paths/instance/transfers/create/Create.stories.tsx
@@ -0,0 +1,45 @@
+/*
+ This file is part of GNU Taler
+ (C) 2021-2023 Taler Systems S.A.
+
+ GNU Taler is free software; you can redistribute it and/or modify it under the
+ terms of the GNU General Public License as published by the Free Software
+ Foundation; either version 3, or (at your option) any later version.
+
+ GNU Taler is distributed in the hope that it will be useful, but WITHOUT ANY
+ WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
+ A PARTICULAR PURPOSE.  See the GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License along with
+ GNU Taler; see the file COPYING.  If not, see <http://www.gnu.org/licenses/>
+ */
+
+/**
+ *
+ * @author Sebastian Javier Marchano (sebasjm)
+ */
+
+import { h, VNode, FunctionalComponent } from "preact";
+import { CreatePage as TestedComponent } from "./CreatePage.js";
+
+export default {
+  title: "Pages/Transfer/Create",
+  component: TestedComponent,
+  argTypes: {
+    onUpdate: { action: "onUpdate" },
+    onBack: { action: "onBack" },
+  },
+};
+
+function createExample<Props>(
+  Component: FunctionalComponent<Props>,
+  props: Partial<Props>,
+) {
+  const r = (args: any) => <Component {...args} />;
+  r.args = props;
+  return r;
+}
+
+export const Example = createExample(TestedComponent, {
+  accounts: ["payto://x-taler-bank/account1", "payto://x-taler-bank/account2"],
+});
diff --git 
a/packages/auditor-backoffice-ui/src/paths/instance/transfers/create/CreatePage.tsx
 
b/packages/auditor-backoffice-ui/src/paths/instance/transfers/create/CreatePage.tsx
new file mode 100644
index 000000000..13f5f3c12
--- /dev/null
+++ 
b/packages/auditor-backoffice-ui/src/paths/instance/transfers/create/CreatePage.tsx
@@ -0,0 +1,146 @@
+/*
+ This file is part of GNU Taler
+ (C) 2021-2023 Taler Systems S.A.
+
+ GNU Taler is free software; you can redistribute it and/or modify it under the
+ terms of the GNU General Public License as published by the Free Software
+ Foundation; either version 3, or (at your option) any later version.
+
+ GNU Taler is distributed in the hope that it will be useful, but WITHOUT ANY
+ WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
+ A PARTICULAR PURPOSE.  See the GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License along with
+ GNU Taler; see the file COPYING.  If not, see <http://www.gnu.org/licenses/>
+ */
+
+/**
+ *
+ * @author Sebastian Javier Marchano (sebasjm)
+ */
+
+import { useTranslationContext } from "@gnu-taler/web-util/browser";
+import { h, VNode } from "preact";
+import { useState } from "preact/hooks";
+import { AsyncButton } from "../../../../components/exception/AsyncButton.js";
+import {
+  FormErrors,
+  FormProvider,
+} from "../../../../components/form/FormProvider.js";
+import { Input } from "../../../../components/form/Input.js";
+import { InputCurrency } from "../../../../components/form/InputCurrency.js";
+import { InputSelector } from "../../../../components/form/InputSelector.js";
+import { useConfigContext } from "../../../../context/config.js";
+import { MerchantBackend } from "../../../../declaration.js";
+import {
+  CROCKFORD_BASE32_REGEX,
+  URL_REGEX,
+} from "../../../../utils/constants.js";
+
+type Entity = MerchantBackend.Transfers.TransferInformation;
+
+interface Props {
+  onCreate: (d: Entity) => Promise<void>;
+  onBack?: () => void;
+  accounts: string[];
+}
+
+export function CreatePage({ accounts, onCreate, onBack }: Props): VNode {
+  const { i18n } = useTranslationContext();
+  const { currency } = useConfigContext();
+
+  const [state, setState] = useState<Partial<Entity>>({
+    wtid: "",
+    // payto_uri: ,
+    // exchange_url: 'http://exchange.taler:8081/',
+    credit_amount: ``,
+  });
+
+  const errors: FormErrors<Entity> = {
+    wtid: !state.wtid
+      ? i18n.str`cannot be empty`
+      : !CROCKFORD_BASE32_REGEX.test(state.wtid)
+      ? i18n.str`check the id, does not look valid`
+      : state.wtid.length !== 52
+      ? i18n.str`should have 52 characters, current ${state.wtid.length}`
+      : undefined,
+    payto_uri: !state.payto_uri ? i18n.str`cannot be empty` : undefined,
+    credit_amount: !state.credit_amount ? i18n.str`cannot be empty` : 
undefined,
+    exchange_url: !state.exchange_url
+      ? i18n.str`cannot be empty`
+      : !URL_REGEX.test(state.exchange_url)
+      ? i18n.str`URL doesn't have the right format`
+      : undefined,
+  };
+
+  const hasErrors = Object.keys(errors).some(
+    (k) => (errors as any)[k] !== undefined,
+  );
+
+  const submitForm = () => {
+    if (hasErrors) return Promise.reject();
+    return onCreate(state as any);
+  };
+
+  return (
+    <div>
+      <section class="section is-main-section">
+        <div class="columns">
+          <div class="column" />
+          <div class="column is-four-fifths">
+            <FormProvider
+              object={state}
+              valueHandler={setState}
+              errors={errors}
+            >
+              <InputSelector
+                name="payto_uri"
+                label={i18n.str`Credited bank account`}
+                values={accounts}
+                placeholder={i18n.str`Select one account`}
+                tooltip={i18n.str`Bank account of the merchant where the 
payment was received`}
+              />
+              <Input<Entity>
+                name="wtid"
+                label={i18n.str`Wire transfer ID`}
+                help=""
+                tooltip={i18n.str`unique identifier of the wire transfer used 
by the exchange, must be 52 characters long`}
+              />
+              <Input<Entity>
+                name="exchange_url"
+                label={i18n.str`Exchange URL`}
+                tooltip={i18n.str`Base URL of the exchange that made the 
transfer, should have been in the wire transfer subject`}
+                help="http://exchange.taler:8081/";
+              />
+              <InputCurrency<Entity>
+                name="credit_amount"
+                label={i18n.str`Amount credited`}
+                tooltip={i18n.str`Actual amount that was wired to the 
merchant's bank account`}
+              />
+            </FormProvider>
+
+            <div class="buttons is-right mt-5">
+              {onBack && (
+                <button class="button" onClick={onBack}>
+                  <i18n.Translate>Cancel</i18n.Translate>
+                </button>
+              )}
+              <AsyncButton
+                disabled={hasErrors}
+                data-tooltip={
+                  hasErrors
+                    ? i18n.str`Need to complete marked fields`
+                    : "confirm operation"
+                }
+                onClick={submitForm}
+              >
+                <i18n.Translate>Confirm</i18n.Translate>
+              </AsyncButton>
+            </div>
+          </div>
+          <div class="column" />
+        </div>
+      </section>
+    </div>
+  );
+}
diff --git 
a/packages/auditor-backoffice-ui/src/paths/instance/transfers/create/index.tsx 
b/packages/auditor-backoffice-ui/src/paths/instance/transfers/create/index.tsx
new file mode 100644
index 000000000..25551a031
--- /dev/null
+++ 
b/packages/auditor-backoffice-ui/src/paths/instance/transfers/create/index.tsx
@@ -0,0 +1,68 @@
+/*
+ This file is part of GNU Taler
+ (C) 2021-2023 Taler Systems S.A.
+
+ GNU Taler is free software; you can redistribute it and/or modify it under the
+ terms of the GNU General Public License as published by the Free Software
+ Foundation; either version 3, or (at your option) any later version.
+
+ GNU Taler is distributed in the hope that it will be useful, but WITHOUT ANY
+ WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
+ A PARTICULAR PURPOSE.  See the GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License along with
+ GNU Taler; see the file COPYING.  If not, see <http://www.gnu.org/licenses/>
+ */
+
+/**
+ *
+ * @author Sebastian Javier Marchano (sebasjm)
+ */
+
+import { useTranslationContext } from "@gnu-taler/web-util/browser";
+import { Fragment, h, VNode } from "preact";
+import { useState } from "preact/hooks";
+import { NotificationCard } from "../../../../components/menu/index.js";
+import { MerchantBackend } from "../../../../declaration.js";
+import { useInstanceDetails } from "../../../../hooks/instance.js";
+import { useTransferAPI } from "../../../../hooks/transfer.js";
+import { Notification } from "../../../../utils/types.js";
+import { CreatePage } from "./CreatePage.js";
+import { useBankAccountDetails, useInstanceBankAccounts } from 
"../../../../hooks/bank.js";
+
+export type Entity = MerchantBackend.Transfers.TransferInformation;
+interface Props {
+  onBack?: () => void;
+  onConfirm: () => void;
+}
+
+export default function CreateTransfer({ onConfirm, onBack }: Props): VNode {
+  const { informTransfer } = useTransferAPI();
+  const [notif, setNotif] = useState<Notification | undefined>(undefined);
+  const { i18n } = useTranslationContext();
+  const instance = useInstanceBankAccounts();
+  const accounts = !instance.ok
+    ? []
+    : instance.data.accounts.map((a) => a.payto_uri);
+
+  return (
+    <>
+      <NotificationCard notification={notif} />
+      <CreatePage
+        onBack={onBack}
+        accounts={accounts}
+        onCreate={(request: MerchantBackend.Transfers.TransferInformation) => {
+          return informTransfer(request)
+            .then(() => onConfirm())
+            .catch((error) => {
+              setNotif({
+                message: i18n.str`could not inform transfer`,
+                type: "ERROR",
+                description: error.message,
+              });
+            });
+        }}
+      />
+    </>
+  );
+}
diff --git 
a/packages/auditor-backoffice-ui/src/paths/instance/transfers/list/List.stories.tsx
 
b/packages/auditor-backoffice-ui/src/paths/instance/transfers/list/List.stories.tsx
new file mode 100644
index 000000000..92b3f9853
--- /dev/null
+++ 
b/packages/auditor-backoffice-ui/src/paths/instance/transfers/list/List.stories.tsx
@@ -0,0 +1,93 @@
+/*
+ This file is part of GNU Taler
+ (C) 2021-2023 Taler Systems S.A.
+
+ GNU Taler is free software; you can redistribute it and/or modify it under the
+ terms of the GNU General Public License as published by the Free Software
+ Foundation; either version 3, or (at your option) any later version.
+
+ GNU Taler is distributed in the hope that it will be useful, but WITHOUT ANY
+ WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
+ A PARTICULAR PURPOSE.  See the GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License along with
+ GNU Taler; see the file COPYING.  If not, see <http://www.gnu.org/licenses/>
+ */
+
+/**
+ *
+ * @author Sebastian Javier Marchano (sebasjm)
+ */
+
+import { h, VNode, FunctionalComponent } from "preact";
+import { ListPage as TestedComponent } from "./ListPage.js";
+
+export default {
+  title: "Pages/Transfer/List",
+  component: TestedComponent,
+  argTypes: {
+    onCreate: { action: "onCreate" },
+    onDelete: { action: "onDelete" },
+    onLoadMoreBefore: { action: "onLoadMoreBefore" },
+    onLoadMoreAfter: { action: "onLoadMoreAfter" },
+    onShowAll: { action: "onShowAll" },
+    onShowVerified: { action: "onShowVerified" },
+    onShowUnverified: { action: "onShowUnverified" },
+    onChangePayTo: { action: "onChangePayTo" },
+  },
+};
+
+function createExample<Props>(
+  Component: FunctionalComponent<Props>,
+  props: Partial<Props>,
+) {
+  const r = (args: any) => <Component {...args} />;
+  r.args = props;
+  return r;
+}
+
+export const Example = createExample(TestedComponent, {
+  transfers: [
+    {
+      exchange_url: "http://exchange.url/";,
+      credit_amount: "TESTKUDOS:10",
+      payto_uri: "payto//x-taler-bank/bank:8080/account",
+      transfer_serial_id: 123123123,
+      wtid: "!@KJELQKWEJ!L@K#!J@",
+      confirmed: true,
+      execution_time: {
+        t_s: new Date().getTime() / 1000,
+      },
+      verified: false,
+    },
+    {
+      exchange_url: "http://exchange.url/";,
+      credit_amount: "TESTKUDOS:10",
+      payto_uri: "payto//x-taler-bank/bank:8080/account",
+      transfer_serial_id: 123123123,
+      wtid: "!@KJELQKWEJ!L@K#!J@",
+      confirmed: true,
+      execution_time: {
+        t_s: new Date().getTime() / 1000,
+      },
+      verified: false,
+    },
+    {
+      exchange_url: "http://exchange.url/";,
+      credit_amount: "TESTKUDOS:10",
+      payto_uri: "payto//x-taler-bank/bank:8080/account",
+      transfer_serial_id: 123123123,
+      wtid: "!@KJELQKWEJ!L@K#!J@",
+      confirmed: true,
+      execution_time: {
+        t_s: new Date().getTime() / 1000,
+      },
+      verified: false,
+    },
+  ],
+  accounts: ["payto://x-taler-bank/bank/some_account"],
+});
+export const Empty = createExample(TestedComponent, {
+  transfers: [],
+  accounts: [],
+});
diff --git 
a/packages/auditor-backoffice-ui/src/paths/instance/transfers/list/ListPage.tsx 
b/packages/auditor-backoffice-ui/src/paths/instance/transfers/list/ListPage.tsx
new file mode 100644
index 000000000..02b12c4c2
--- /dev/null
+++ 
b/packages/auditor-backoffice-ui/src/paths/instance/transfers/list/ListPage.tsx
@@ -0,0 +1,134 @@
+/*
+ This file is part of GNU Taler
+ (C) 2021-2023 Taler Systems S.A.
+
+ GNU Taler is free software; you can redistribute it and/or modify it under the
+ terms of the GNU General Public License as published by the Free Software
+ Foundation; either version 3, or (at your option) any later version.
+
+ GNU Taler is distributed in the hope that it will be useful, but WITHOUT ANY
+ WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
+ A PARTICULAR PURPOSE.  See the GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License along with
+ GNU Taler; see the file COPYING.  If not, see <http://www.gnu.org/licenses/>
+ */
+
+/**
+ *
+ * @author Sebastian Javier Marchano (sebasjm)
+ */
+
+import { useTranslationContext } from "@gnu-taler/web-util/browser";
+import { h, VNode } from "preact";
+import { FormProvider } from "../../../../components/form/FormProvider.js";
+import { InputSelector } from "../../../../components/form/InputSelector.js";
+import { MerchantBackend } from "../../../../declaration.js";
+import { CardTable } from "./Table.js";
+
+export interface Props {
+  transfers: MerchantBackend.Transfers.TransferDetails[];
+  onLoadMoreBefore?: () => void;
+  onLoadMoreAfter?: () => void;
+  onShowAll: () => void;
+  onShowVerified: () => void;
+  onShowUnverified: () => void;
+  isVerifiedTransfers?: boolean;
+  isNonVerifiedTransfers?: boolean;
+  isAllTransfers?: boolean;
+  accounts: string[];
+  onChangePayTo: (p?: string) => void;
+  payTo?: string;
+  onCreate: () => void;
+  onDelete: () => void;
+}
+
+export function ListPage({
+  payTo,
+  onChangePayTo,
+  transfers,
+  onCreate,
+  onDelete,
+  accounts,
+  onLoadMoreBefore,
+  onLoadMoreAfter,
+  isAllTransfers,
+  isNonVerifiedTransfers,
+  isVerifiedTransfers,
+  onShowAll,
+  onShowUnverified,
+  onShowVerified,
+}: Props): VNode {
+  const form = { payto_uri: payTo };
+
+  const { i18n } = useTranslationContext();
+  return (
+    <section class="section is-main-section">
+      <div class="columns">
+        <div class="column" />
+        <div class="column is-10">
+          <FormProvider
+            object={form}
+            valueHandler={(updater) => onChangePayTo(updater(form).payto_uri)}
+          >
+            <InputSelector
+              name="payto_uri"
+              label={i18n.str`Account URI`}
+              values={accounts}
+              placeholder={i18n.str`Select one account`}
+              tooltip={i18n.str`filter by account address`}
+            />
+          </FormProvider>
+        </div>
+        <div class="column" />
+      </div>
+      <div class="tabs">
+        <ul>
+          <li class={isAllTransfers ? "is-active" : ""}>
+            <div
+              class="has-tooltip-right"
+              data-tooltip={i18n.str`remove all filters`}
+            >
+              <a onClick={onShowAll}>
+                <i18n.Translate>All</i18n.Translate>
+              </a>
+            </div>
+          </li>
+          <li class={isVerifiedTransfers ? "is-active" : ""}>
+            <div
+              class="has-tooltip-right"
+              data-tooltip={i18n.str`only show wire transfers confirmed by the 
merchant`}
+            >
+              <a onClick={onShowVerified}>
+                <i18n.Translate>Verified</i18n.Translate>
+              </a>
+            </div>
+          </li>
+          <li class={isNonVerifiedTransfers ? "is-active" : ""}>
+            <div
+              class="has-tooltip-right"
+              data-tooltip={i18n.str`only show wire transfers claimed by the 
exchange`}
+            >
+              <a onClick={onShowUnverified}>
+                <i18n.Translate>Unverified</i18n.Translate>
+              </a>
+            </div>
+          </li>
+        </ul>
+      </div>
+      <CardTable
+        transfers={transfers.map((o) => ({
+          ...o,
+          id: String(o.transfer_serial_id),
+        }))}
+        accounts={accounts}
+        onCreate={onCreate}
+        onDelete={onDelete}
+        onLoadMoreBefore={onLoadMoreBefore}
+        hasMoreBefore={!onLoadMoreBefore}
+        onLoadMoreAfter={onLoadMoreAfter}
+        hasMoreAfter={!onLoadMoreAfter}
+      />
+    </section>
+  );
+}
diff --git 
a/packages/auditor-backoffice-ui/src/paths/instance/transfers/list/Table.tsx 
b/packages/auditor-backoffice-ui/src/paths/instance/transfers/list/Table.tsx
new file mode 100644
index 000000000..b6b1cf328
--- /dev/null
+++ b/packages/auditor-backoffice-ui/src/paths/instance/transfers/list/Table.tsx
@@ -0,0 +1,229 @@
+/*
+ This file is part of GNU Taler
+ (C) 2021-2023 Taler Systems S.A.
+
+ GNU Taler is free software; you can redistribute it and/or modify it under the
+ terms of the GNU General Public License as published by the Free Software
+ Foundation; either version 3, or (at your option) any later version.
+
+ GNU Taler is distributed in the hope that it will be useful, but WITHOUT ANY
+ WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
+ A PARTICULAR PURPOSE.  See the GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License along with
+ GNU Taler; see the file COPYING.  If not, see <http://www.gnu.org/licenses/>
+ */
+
+/**
+ *
+ * @author Sebastian Javier Marchano (sebasjm)
+ */
+
+import { useTranslationContext } from "@gnu-taler/web-util/browser";
+import { format } from "date-fns";
+import { h, VNode } from "preact";
+import { StateUpdater, useState } from "preact/hooks";
+import { MerchantBackend, WithId } from "../../../../declaration.js";
+import { datetimeFormatForSettings, useSettings } from 
"../../../../hooks/useSettings.js";
+
+type Entity = MerchantBackend.Transfers.TransferDetails & WithId;
+
+interface Props {
+  transfers: Entity[];
+  onDelete: (id: Entity) => void;
+  onCreate: () => void;
+  accounts: string[];
+  onLoadMoreBefore?: () => void;
+  hasMoreBefore?: boolean;
+  hasMoreAfter?: boolean;
+  onLoadMoreAfter?: () => void;
+}
+
+export function CardTable({
+  transfers,
+  onCreate,
+  onDelete,
+  onLoadMoreAfter,
+  onLoadMoreBefore,
+  hasMoreAfter,
+  hasMoreBefore,
+}: Props): VNode {
+  const [rowSelection, rowSelectionHandler] = useState<string[]>([]);
+
+  const { i18n } = useTranslationContext();
+
+  return (
+    <div class="card has-table">
+      <header class="card-header">
+        <p class="card-header-title">
+          <span class="icon">
+            <i class="mdi mdi-arrow-left-right" />
+          </span>
+          <i18n.Translate>Transfers</i18n.Translate>
+        </p>
+        <div class="card-header-icon" aria-label="more options">
+          <span
+            class="has-tooltip-left"
+            data-tooltip={i18n.str`add new transfer`}
+          >
+            <button class="button is-info" type="button" onClick={onCreate}>
+              <span class="icon is-small">
+                <i class="mdi mdi-plus mdi-36px" />
+              </span>
+            </button>
+          </span>
+        </div>
+      </header>
+      <div class="card-content">
+        <div class="b-table has-pagination">
+          <div class="table-wrapper has-mobile-cards">
+            {transfers.length > 0 ? (
+              <Table
+                instances={transfers}
+                onDelete={onDelete}
+                rowSelection={rowSelection}
+                rowSelectionHandler={rowSelectionHandler}
+                onLoadMoreAfter={onLoadMoreAfter}
+                onLoadMoreBefore={onLoadMoreBefore}
+                hasMoreAfter={hasMoreAfter}
+                hasMoreBefore={hasMoreBefore}
+              />
+            ) : (
+              <EmptyTable />
+            )}
+          </div>
+        </div>
+      </div>
+    </div>
+  );
+}
+interface TableProps {
+  rowSelection: string[];
+  instances: Entity[];
+  onDelete: (id: Entity) => void;
+  rowSelectionHandler: StateUpdater<string[]>;
+  onLoadMoreBefore?: () => void;
+  hasMoreBefore?: boolean;
+  hasMoreAfter?: boolean;
+  onLoadMoreAfter?: () => void;
+}
+
+function toggleSelected<T>(id: T): (prev: T[]) => T[] {
+  return (prev: T[]): T[] =>
+    prev.indexOf(id) == -1 ? [...prev, id] : prev.filter((e) => e != id);
+}
+
+function Table({
+  instances,
+  onLoadMoreAfter,
+  onDelete,
+  onLoadMoreBefore,
+  hasMoreAfter,
+  hasMoreBefore,
+}: TableProps): VNode {
+  const { i18n } = useTranslationContext();
+  const [settings] = useSettings();
+  return (
+    <div class="table-container">
+      {hasMoreBefore && (
+        <button
+          class="button is-fullwidth"
+          data-tooltip={i18n.str`load more transfers before the first one`}
+          onClick={onLoadMoreBefore}
+        >
+          <i18n.Translate>load newer transfers</i18n.Translate>
+        </button>
+      )}
+      <table class="table is-fullwidth is-striped is-hoverable is-fullwidth">
+        <thead>
+          <tr>
+            <th>
+              <i18n.Translate>ID</i18n.Translate>
+            </th>
+            <th>
+              <i18n.Translate>Credit</i18n.Translate>
+            </th>
+            <th>
+              <i18n.Translate>Address</i18n.Translate>
+            </th>
+            <th>
+              <i18n.Translate>Exchange URL</i18n.Translate>
+            </th>
+            <th>
+              <i18n.Translate>Confirmed</i18n.Translate>
+            </th>
+            <th>
+              <i18n.Translate>Verified</i18n.Translate>
+            </th>
+            <th>
+              <i18n.Translate>Executed at</i18n.Translate>
+            </th>
+            <th />
+          </tr>
+        </thead>
+        <tbody>
+          {instances.map((i) => {
+            return (
+              <tr key={i.id}>
+                <td>{i.id}</td>
+                <td>{i.credit_amount}</td>
+                <td>{i.payto_uri}</td>
+                <td>{i.exchange_url}</td>
+                <td>{i.confirmed ? i18n.str`yes` : i18n.str`no`}</td>
+                <td>{i.verified ? i18n.str`yes` : i18n.str`no`}</td>
+                <td>
+                  {i.execution_time
+                    ? i.execution_time.t_s == "never"
+                      ? i18n.str`never`
+                      : format(
+                        i.execution_time.t_s * 1000,
+                        datetimeFormatForSettings(settings),
+                      )
+                    : i18n.str`unknown`}
+                </td>
+                <td>
+                  {i.verified === undefined ? (
+                    <button
+                      class="button is-danger is-small has-tooltip-left"
+                      data-tooltip={i18n.str`delete selected transfer from the 
database`}
+                      onClick={() => onDelete(i)}
+                    >
+                      Delete
+                    </button>
+                  ) : undefined}
+                </td>
+              </tr>
+            );
+          })}
+        </tbody>
+      </table>
+      {hasMoreAfter && (
+        <button
+          class="button is-fullwidth"
+          data-tooltip={i18n.str`load more transfer after the last one`}
+          onClick={onLoadMoreAfter}
+        >
+          <i18n.Translate>load older transfers</i18n.Translate>
+        </button>
+      )}
+    </div>
+  );
+}
+
+function EmptyTable(): VNode {
+  const { i18n } = useTranslationContext();
+  return (
+    <div class="content has-text-grey has-text-centered">
+      <p>
+        <span class="icon is-large">
+          <i class="mdi mdi-emoticon-sad mdi-48px" />
+        </span>
+      </p>
+      <p>
+        <i18n.Translate>
+          There is no transfer yet, add more pressing the + sign
+        </i18n.Translate>
+      </p>
+    </div>
+  );
+}
diff --git 
a/packages/auditor-backoffice-ui/src/paths/instance/transfers/list/index.tsx 
b/packages/auditor-backoffice-ui/src/paths/instance/transfers/list/index.tsx
new file mode 100644
index 000000000..0fdbb9bc3
--- /dev/null
+++ b/packages/auditor-backoffice-ui/src/paths/instance/transfers/list/index.tsx
@@ -0,0 +1,118 @@
+/*
+ This file is part of GNU Taler
+ (C) 2021-2023 Taler Systems S.A.
+
+ GNU Taler is free software; you can redistribute it and/or modify it under the
+ terms of the GNU General Public License as published by the Free Software
+ Foundation; either version 3, or (at your option) any later version.
+
+ GNU Taler is distributed in the hope that it will be useful, but WITHOUT ANY
+ WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
+ A PARTICULAR PURPOSE.  See the GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License along with
+ GNU Taler; see the file COPYING.  If not, see <http://www.gnu.org/licenses/>
+ */
+
+/**
+ *
+ * @author Sebastian Javier Marchano (sebasjm)
+ */
+
+import { ErrorType, HttpError } from "@gnu-taler/web-util/browser";
+import { h, VNode } from "preact";
+import { useEffect, useState } from "preact/hooks";
+import { Loading } from "../../../../components/exception/loading.js";
+import { MerchantBackend } from "../../../../declaration.js";
+import { useInstanceDetails } from "../../../../hooks/instance.js";
+import { useInstanceTransfers } from "../../../../hooks/transfer.js";
+import { ListPage } from "./ListPage.js";
+import { HttpStatusCode } from "@gnu-taler/taler-util";
+import { useInstanceBankAccounts } from "../../../../hooks/bank.js";
+
+interface Props {
+  onUnauthorized: () => VNode;
+  onLoadError: (error: HttpError<MerchantBackend.ErrorDetail>) => VNode;
+  onNotFound: () => VNode;
+  onCreate: () => void;
+}
+interface Form {
+  verified?: "yes" | "no";
+  payto_uri?: string;
+}
+
+export default function ListTransfer({
+  onUnauthorized,
+  onLoadError,
+  onCreate,
+  onNotFound,
+}: Props): VNode {
+  const setFilter = (s?: "yes" | "no") => setForm({ ...form, verified: s });
+
+  const [position, setPosition] = useState<string | undefined>(undefined);
+
+  const instance = useInstanceBankAccounts();
+  const accounts = !instance.ok
+    ? []
+    : instance.data.accounts.map((a) => a.payto_uri);
+  const [form, setForm] = useState<Form>({ payto_uri: "" });
+
+  const shoulUseDefaultAccount = accounts.length === 1
+  useEffect(() => {
+    if (shoulUseDefaultAccount) {
+      setForm({...form, payto_uri: accounts[0]})
+    }
+  }, [shoulUseDefaultAccount])
+
+  const isVerifiedTransfers = form.verified === "yes";
+  const isNonVerifiedTransfers = form.verified === "no";
+  const isAllTransfers = form.verified === undefined;
+
+  const result = useInstanceTransfers(
+    {
+      position,
+      payto_uri: form.payto_uri === "" ? undefined : form.payto_uri,
+      verified: form.verified,
+    },
+    (id) => setPosition(id),
+  );
+
+  if (result.loading) return <Loading />;
+  if (!result.ok) {
+    if (
+      result.type === ErrorType.CLIENT &&
+      result.status === HttpStatusCode.Unauthorized
+    )
+      return onUnauthorized();
+    if (
+      result.type === ErrorType.CLIENT &&
+      result.status === HttpStatusCode.NotFound
+    )
+      return onNotFound();
+    return onLoadError(result);
+  }
+
+  return (
+    <ListPage
+      accounts={accounts}
+      transfers={result.data.transfers}
+      onLoadMoreBefore={
+        result.isReachingStart ? result.loadMorePrev : undefined
+      }
+      onLoadMoreAfter={result.isReachingEnd ? result.loadMore : undefined}
+      onCreate={onCreate}
+      onDelete={() => {
+        null;
+      }}
+      // position={position} setPosition={setPosition}
+      onShowAll={() => setFilter(undefined)}
+      onShowUnverified={() => setFilter("no")}
+      onShowVerified={() => setFilter("yes")}
+      isAllTransfers={isAllTransfers}
+      isVerifiedTransfers={isVerifiedTransfers}
+      isNonVerifiedTransfers={isNonVerifiedTransfers}
+      payTo={form.payto_uri}
+      onChangePayTo={(p) => setForm((v) => ({ ...v, payto_uri: p }))}
+    />
+  );
+}
diff --git 
a/packages/auditor-backoffice-ui/src/paths/instance/transfers/update/index.tsx 
b/packages/auditor-backoffice-ui/src/paths/instance/transfers/update/index.tsx
new file mode 100644
index 000000000..84cc95e72
--- /dev/null
+++ 
b/packages/auditor-backoffice-ui/src/paths/instance/transfers/update/index.tsx
@@ -0,0 +1,26 @@
+/*
+ This file is part of GNU Taler
+ (C) 2021-2023 Taler Systems S.A.
+
+ GNU Taler is free software; you can redistribute it and/or modify it under the
+ terms of the GNU General Public License as published by the Free Software
+ Foundation; either version 3, or (at your option) any later version.
+
+ GNU Taler is distributed in the hope that it will be useful, but WITHOUT ANY
+ WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
+ A PARTICULAR PURPOSE.  See the GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License along with
+ GNU Taler; see the file COPYING.  If not, see <http://www.gnu.org/licenses/>
+ */
+
+/**
+ *
+ * @author Sebastian Javier Marchano (sebasjm)
+ */
+
+import { h, VNode } from "preact";
+
+export default function UpdateTransfer(): VNode {
+  return <div>order transfer page</div>;
+}
diff --git 
a/packages/auditor-backoffice-ui/src/paths/instance/update/Update.stories.tsx 
b/packages/auditor-backoffice-ui/src/paths/instance/update/Update.stories.tsx
new file mode 100644
index 000000000..817a7025c
--- /dev/null
+++ 
b/packages/auditor-backoffice-ui/src/paths/instance/update/Update.stories.tsx
@@ -0,0 +1,59 @@
+/*
+ This file is part of GNU Taler
+ (C) 2021-2023 Taler Systems S.A.
+
+ GNU Taler is free software; you can redistribute it and/or modify it under the
+ terms of the GNU General Public License as published by the Free Software
+ Foundation; either version 3, or (at your option) any later version.
+
+ GNU Taler is distributed in the hope that it will be useful, but WITHOUT ANY
+ WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
+ A PARTICULAR PURPOSE.  See the GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License along with
+ GNU Taler; see the file COPYING.  If not, see <http://www.gnu.org/licenses/>
+ */
+
+/**
+ *
+ * @author Sebastian Javier Marchano (sebasjm)
+ */
+
+import { h, VNode, FunctionalComponent } from "preact";
+import { UpdatePage as TestedComponent } from "./UpdatePage.js";
+
+export default {
+  title: "Pages/Instance/Update",
+  component: TestedComponent,
+  argTypes: {
+    onUpdate: { action: "onUpdate" },
+    onBack: { action: "onBack" },
+  },
+};
+
+function createExample<Props>(
+  Component: FunctionalComponent<Props>,
+  props: Partial<Props>,
+) {
+  const r = (args: any) => <Component {...args} />;
+  r.args = props;
+  return r;
+}
+
+export const Example = createExample(TestedComponent, {
+  selected: {
+    name: "name",
+    auth: { method: "external" },
+    address: {},
+    user_type: "business",
+    use_stefan: true,
+    jurisdiction: {},
+    default_pay_delay: {
+      d_us: 1000 * 1000, //one second
+    },
+    default_wire_transfer_delay: {
+      d_us: 1000 * 1000, //one second
+    },
+    merchant_pub: "ASDWQEKASJDKSADJ",
+  },
+});
diff --git 
a/packages/auditor-backoffice-ui/src/paths/instance/update/UpdatePage.tsx 
b/packages/auditor-backoffice-ui/src/paths/instance/update/UpdatePage.tsx
new file mode 100644
index 000000000..a27a0cb06
--- /dev/null
+++ b/packages/auditor-backoffice-ui/src/paths/instance/update/UpdatePage.tsx
@@ -0,0 +1,176 @@
+/*
+ This file is part of GNU Taler
+ (C) 2021-2023 Taler Systems S.A.
+
+ GNU Taler is free software; you can redistribute it and/or modify it under the
+ terms of the GNU General Public License as published by the Free Software
+ Foundation; either version 3, or (at your option) any later version.
+
+ GNU Taler is distributed in the hope that it will be useful, but WITHOUT ANY
+ WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
+ A PARTICULAR PURPOSE.  See the GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License along with
+ GNU Taler; see the file COPYING.  If not, see <http://www.gnu.org/licenses/>
+ */
+
+/**
+ *
+ * @author Sebastian Javier Marchano (sebasjm)
+ */
+
+import { useTranslationContext } from "@gnu-taler/web-util/browser";
+import { h, VNode } from "preact";
+import { useState } from "preact/hooks";
+import { AsyncButton } from "../../../components/exception/AsyncButton.js";
+import {
+  FormErrors,
+  FormProvider,
+} from "../../../components/form/FormProvider.js";
+import { DefaultInstanceFormFields } from 
"../../../components/instance/DefaultInstanceFormFields.js";
+import { useInstanceContext } from "../../../context/instance.js";
+import { MerchantBackend } from "../../../declaration.js";
+import { undefinedIfEmpty } from "../../../utils/table.js";
+import { Duration } from "@gnu-taler/taler-util";
+
+export type Entity = 
Omit<Omit<MerchantBackend.Instances.InstanceReconfigurationMessage, 
"default_pay_delay">, "default_wire_transfer_delay"> & {
+  default_pay_delay: Duration,
+  default_wire_transfer_delay: Duration,
+};
+
+//MerchantBackend.Instances.InstanceAuthConfigurationMessage
+interface Props {
+  onUpdate: (d: MerchantBackend.Instances.InstanceReconfigurationMessage) => 
void;
+  selected: MerchantBackend.Instances.QueryInstancesResponse;
+  isLoading: boolean;
+  onBack: () => void;
+}
+
+function convert(
+  from: MerchantBackend.Instances.QueryInstancesResponse,
+): Entity {
+  const { default_pay_delay, default_wire_transfer_delay, ...rest } = from;
+
+  const defaults = {
+    use_stefan: false,
+    default_pay_delay: Duration.fromTalerProtocolDuration(default_pay_delay),
+    default_wire_transfer_delay: 
Duration.fromTalerProtocolDuration(default_wire_transfer_delay),
+  };
+  return { ...defaults, ...rest };
+}
+
+export function UpdatePage({
+  onUpdate,
+  selected,
+  onBack,
+}: Props): VNode {
+  const { id } = useInstanceContext();
+
+  const [value, valueHandler] = useState<Partial<Entity>>(convert(selected));
+
+  const { i18n } = useTranslationContext();
+
+  const errors: FormErrors<Entity> = {
+    name: !value.name ? i18n.str`required` : undefined,
+    user_type: !value.user_type
+      ? i18n.str`required`
+      : value.user_type !== "business" && value.user_type !== "individual"
+        ? i18n.str`should be business or individual`
+        : undefined,
+    default_pay_delay: !value.default_pay_delay
+      ? i18n.str`required`
+      : !!value.default_wire_transfer_delay &&
+        value.default_wire_transfer_delay.d_ms !== "forever" &&
+        value.default_pay_delay.d_ms !== "forever" &&
+        value.default_pay_delay.d_ms > value.default_wire_transfer_delay.d_ms ?
+        i18n.str`pay delay can't be greater than wire transfer delay` : 
undefined,
+    default_wire_transfer_delay: !value.default_wire_transfer_delay
+      ? i18n.str`required`
+      : undefined,
+    address: undefinedIfEmpty({
+      address_lines:
+        value.address?.address_lines && value.address?.address_lines.length > 7
+          ? i18n.str`max 7 lines`
+          : undefined,
+    }),
+    jurisdiction: undefinedIfEmpty({
+      address_lines:
+        value.address?.address_lines && value.address?.address_lines.length > 7
+          ? i18n.str`max 7 lines`
+          : undefined,
+    }),
+  };
+
+  const hasErrors = Object.keys(errors).some(
+    (k) => (errors as any)[k] !== undefined,
+  );
+
+  const submit = async (): Promise<void> => {
+    const { default_pay_delay, default_wire_transfer_delay, ...rest } = value 
as Required<Entity>;
+    const result: MerchantBackend.Instances.InstanceReconfigurationMessage = {
+      default_pay_delay: Duration.toTalerProtocolDuration(default_pay_delay),
+      default_wire_transfer_delay: 
Duration.toTalerProtocolDuration(default_wire_transfer_delay),
+      ...rest,
+    }
+    await onUpdate(result);
+  };
+  // const [active, setActive] = useState(false);
+
+  return (
+    <div>
+      <section class="section">
+        <section class="hero is-hero-bar">
+          <div class="hero-body">
+            <div class="level">
+              <div class="level-left">
+                <div class="level-item">
+                  <span class="is-size-4">
+                    <i18n.Translate>Instance id</i18n.Translate>: <b>{id}</b>
+                  </span>
+                </div>
+              </div>
+            </div>
+          </div>
+        </section>
+
+        <hr />
+
+        <div class="columns">
+          <div class="column" />
+          <div class="column is-four-fifths">
+            <FormProvider<Entity>
+              errors={errors}
+              object={value}
+              valueHandler={valueHandler}
+            >
+              <DefaultInstanceFormFields showId={false} />
+            </FormProvider>
+
+            <div class="buttons is-right mt-4">
+              <button
+                class="button"
+                onClick={onBack}
+                data-tooltip="cancel operation"
+              >
+                <i18n.Translate>Cancel</i18n.Translate>
+              </button>
+
+              <AsyncButton
+                onClick={submit}
+                data-tooltip={
+                  hasErrors
+                    ? i18n.str`Need to complete marked fields`
+                    : "confirm operation"
+                }
+                disabled={hasErrors}
+              >
+                <i18n.Translate>Confirm</i18n.Translate>
+              </AsyncButton>
+            </div>
+          </div>
+          <div class="column" />
+        </div>
+      </section>
+    </div>
+  );
+}
diff --git a/packages/auditor-backoffice-ui/src/paths/instance/update/index.tsx 
b/packages/auditor-backoffice-ui/src/paths/instance/update/index.tsx
new file mode 100644
index 000000000..e44cf5c0f
--- /dev/null
+++ b/packages/auditor-backoffice-ui/src/paths/instance/update/index.tsx
@@ -0,0 +1,118 @@
+/*
+ This file is part of GNU Taler
+ (C) 2021-2023 Taler Systems S.A.
+
+ GNU Taler is free software; you can redistribute it and/or modify it under the
+ terms of the GNU General Public License as published by the Free Software
+ Foundation; either version 3, or (at your option) any later version.
+
+ GNU Taler is distributed in the hope that it will be useful, but WITHOUT ANY
+ WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
+ A PARTICULAR PURPOSE.  See the GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License along with
+ GNU Taler; see the file COPYING.  If not, see <http://www.gnu.org/licenses/>
+ */
+import { HttpStatusCode } from "@gnu-taler/taler-util";
+import {
+  ErrorType,
+  HttpError,
+  HttpResponse,
+  useTranslationContext,
+} from "@gnu-taler/web-util/browser";
+import { Fragment, VNode, h } from "preact";
+import { useState } from "preact/hooks";
+import { Loading } from "../../../components/exception/loading.js";
+import { NotificationCard } from "../../../components/menu/index.js";
+import { useInstanceContext } from "../../../context/instance.js";
+import { AccessToken, MerchantBackend } from "../../../declaration.js";
+import {
+  useInstanceAPI,
+  useInstanceDetails,
+  useManagedInstanceDetails,
+  useManagementAPI,
+} from "../../../hooks/instance.js";
+import { Notification } from "../../../utils/types.js";
+import { UpdatePage } from "./UpdatePage.js";
+
+export interface Props {
+  onBack: () => void;
+  onConfirm: () => void;
+
+  onUnauthorized: () => VNode;
+  onNotFound: () => VNode;
+  onLoadError: (e: HttpError<MerchantBackend.ErrorDetail>) => VNode;
+  onUpdateError: (e: HttpError<MerchantBackend.ErrorDetail>) => void;
+}
+
+export default function Update(props: Props): VNode {
+  const { updateInstance } = useInstanceAPI();
+  const result = useInstanceDetails();
+  return CommonUpdate(props, result, updateInstance, );
+}
+
+export function AdminUpdate(props: Props & { instanceId: string }): VNode {
+  const { updateInstance } = useManagementAPI(
+    props.instanceId,
+  );
+  const result = useManagedInstanceDetails(props.instanceId);
+  return CommonUpdate(props, result, updateInstance, );
+}
+
+function CommonUpdate(
+  {
+    onBack,
+    onConfirm,
+    onLoadError,
+    onNotFound,
+    onUpdateError,
+    onUnauthorized,
+  }: Props,
+  result: HttpResponse<
+    MerchantBackend.Instances.QueryInstancesResponse,
+    MerchantBackend.ErrorDetail
+  >,
+  updateInstance: any,
+): VNode {
+  const [notif, setNotif] = useState<Notification | undefined>(undefined);
+  const { i18n } = useTranslationContext();
+
+  if (result.loading) return <Loading />;
+  if (!result.ok) {
+    if (
+      result.type === ErrorType.CLIENT &&
+      result.status === HttpStatusCode.Unauthorized
+    )
+      return onUnauthorized();
+    if (
+      result.type === ErrorType.CLIENT &&
+      result.status === HttpStatusCode.NotFound
+    )
+      return onNotFound();
+    return onLoadError(result);
+  }
+
+  return (
+    <Fragment>
+      <NotificationCard notification={notif} />
+      <UpdatePage
+        onBack={onBack}
+        isLoading={false}
+        selected={result.data}
+        onUpdate={(
+          d: MerchantBackend.Instances.InstanceReconfigurationMessage,
+        ): Promise<void> => {
+          return updateInstance(d)
+            .then(onConfirm)
+            .catch((error: Error) =>
+              setNotif({
+                message: i18n.str`Failed to create instance`,
+                type: "ERROR",
+                description: error.message,
+              }),
+            );
+        }}
+      />
+    </Fragment>
+  );
+}
diff --git 
a/packages/auditor-backoffice-ui/src/paths/instance/webhooks/create/Create.stories.tsx
 
b/packages/auditor-backoffice-ui/src/paths/instance/webhooks/create/Create.stories.tsx
new file mode 100644
index 000000000..4857ede97
--- /dev/null
+++ 
b/packages/auditor-backoffice-ui/src/paths/instance/webhooks/create/Create.stories.tsx
@@ -0,0 +1,28 @@
+/*
+ This file is part of GNU Taler
+ (C) 2021-2023 Taler Systems S.A.
+
+ GNU Taler is free software; you can redistribute it and/or modify it under the
+ terms of the GNU General Public License as published by the Free Software
+ Foundation; either version 3, or (at your option) any later version.
+
+ GNU Taler is distributed in the hope that it will be useful, but WITHOUT ANY
+ WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
+ A PARTICULAR PURPOSE.  See the GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License along with
+ GNU Taler; see the file COPYING.  If not, see <http://www.gnu.org/licenses/>
+ */
+
+/**
+ *
+ * @author Sebastian Javier Marchano (sebasjm)
+ */
+
+import { h, VNode, FunctionalComponent } from "preact";
+import { CreatePage as TestedComponent } from "./CreatePage.js";
+
+export default {
+  title: "Pages/Webhooks/Create",
+  component: TestedComponent,
+};
diff --git 
a/packages/auditor-backoffice-ui/src/paths/instance/webhooks/create/CreatePage.tsx
 
b/packages/auditor-backoffice-ui/src/paths/instance/webhooks/create/CreatePage.tsx
new file mode 100644
index 000000000..434d69412
--- /dev/null
+++ 
b/packages/auditor-backoffice-ui/src/paths/instance/webhooks/create/CreatePage.tsx
@@ -0,0 +1,183 @@
+/*
+ This file is part of GNU Taler
+ (C) 2021-2023 Taler Systems S.A.
+
+ GNU Taler is free software; you can redistribute it and/or modify it under the
+ terms of the GNU General Public License as published by the Free Software
+ Foundation; either version 3, or (at your option) any later version.
+
+ GNU Taler is distributed in the hope that it will be useful, but WITHOUT ANY
+ WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
+ A PARTICULAR PURPOSE.  See the GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License along with
+ GNU Taler; see the file COPYING.  If not, see <http://www.gnu.org/licenses/>
+ */
+
+/**
+ *
+ * @author Sebastian Javier Marchano (sebasjm)
+ */
+
+import { useTranslationContext } from "@gnu-taler/web-util/browser";
+import { Fragment, h, VNode } from "preact";
+import { useState } from "preact/hooks";
+import { AsyncButton } from "../../../../components/exception/AsyncButton.js";
+import {
+  FormErrors,
+  FormProvider,
+} from "../../../../components/form/FormProvider.js";
+import { Input } from "../../../../components/form/Input.js";
+import { InputCurrency } from "../../../../components/form/InputCurrency.js";
+import { InputDuration } from "../../../../components/form/InputDuration.js";
+import { InputNumber } from "../../../../components/form/InputNumber.js";
+import { useBackendContext } from "../../../../context/backend.js";
+import { MerchantBackend } from "../../../../declaration.js";
+import { InputSelector } from "../../../../components/form/InputSelector.js";
+
+type Entity = MerchantBackend.Webhooks.WebhookAddDetails;
+
+interface Props {
+  onCreate: (d: Entity) => Promise<void>;
+  onBack?: () => void;
+}
+
+const validMethod = ["GET", "POST", "PUT", "PATCH", "HEAD"];
+
+export function CreatePage({ onCreate, onBack }: Props): VNode {
+  const { i18n } = useTranslationContext();
+
+  const [state, setState] = useState<Partial<Entity>>({});
+
+  const errors: FormErrors<Entity> = {
+    webhook_id: !state.webhook_id ? i18n.str`required` : undefined,
+    event_type: !state.event_type ? i18n.str`required`
+      : state.event_type !== "pay" && state.event_type !== "refund" ? 
i18n.str`it should be "pay" or "refund"`
+        : undefined,
+    http_method: !state.http_method
+      ? i18n.str`required`
+      : !validMethod.includes(state.http_method)
+        ? i18n.str`should be one of '${validMethod.join(", ")}'`
+        : undefined,
+    url: !state.url ? i18n.str`required` : undefined,
+  };
+
+  const hasErrors = Object.keys(errors).some(
+    (k) => (errors as any)[k] !== undefined,
+  );
+
+  const submitForm = () => {
+    if (hasErrors) return Promise.reject();
+    return onCreate(state as any);
+  };
+
+  return (
+    <div>
+      <section class="section is-main-section">
+        <div class="columns">
+          <div class="column" />
+          <div class="column is-four-fifths">
+            <FormProvider
+              object={state}
+              valueHandler={setState}
+              errors={errors}
+            >
+              <Input<Entity>
+                name="webhook_id"
+                label={i18n.str`ID`}
+                tooltip={i18n.str`Webhook ID to use`}
+              />
+              <InputSelector
+                name="event_type"
+                label={i18n.str`Event`}
+                values={[
+                  i18n.str`Choose one...`,
+                  i18n.str`pay`,
+                  i18n.str`refund`,
+                ]}
+                tooltip={i18n.str`The event of the webhook: why the webhook is 
used`}
+              />
+              <InputSelector
+                name="http_method"
+                label={i18n.str`Method`}
+                values={[
+                  i18n.str`Choose one...`,
+                  i18n.str`GET`,
+                  i18n.str`POST`,
+                  i18n.str`PUT`,
+                  i18n.str`PATCH`,
+                  i18n.str`HEAD`,
+                ]}
+                tooltip={i18n.str`Method used by the webhook`}
+              />
+
+              <Input<Entity>
+                name="url"
+                label={i18n.str`URL`}
+                tooltip={i18n.str`URL of the webhook where the customer will 
be redirected`}
+              />
+
+              <p>
+                The text below support <a target="_blank" rel="noreferrer" 
href="https://mustache.github.io/mustache.5.html";>mustache</a> template engine. 
Any string
+                between <pre style={{ display: "inline", padding: 0 
}}>&#123;&#123;</pre> and <pre style={{ display: "inline", padding: 0 
}}>&#125;&#125;</pre> will
+                be replaced with replaced with the value of the correspoding 
variable.
+              </p>
+              <p>
+                For example <pre style={{ display: "inline", padding: 0 
}}>&#123;&#123;contract_terms.amount&#125;&#125;</pre> will be replaced
+                with the the order's price
+              </p>
+              <p>
+                The short list of variables are:
+              </p>
+              <div class="menu">
+
+                <ul class="menu-list" style={{ listStyleType: "disc", 
marginLeft: 20 }}>
+                  <li><b>contract_terms.summary:</b> order's description </li>
+                  <li><b>contract_terms.amount:</b> order's price </li>
+                  <li><b>order_id:</b> order's unique identification </li>
+                  {state.event_type === "refund" && <Fragment>
+                    <li><b>refund_amout:</b> the amount that was being 
refunded</li>
+                    <li><b>reason:</b> the reason entered by the merchant 
staff for granting the refund</li>
+                    <li><b>timestamp:</b> time of the refund in nanoseconds 
since 1970</li>
+                  </Fragment>}
+                </ul>
+              </div>
+              {/* <Input<Entity>
+                name="header_template"
+                label={i18n.str`Http header`}
+                inputType="multiline"
+                tooltip={i18n.str`Header template of the webhook`}
+              /> */}
+              <Input<Entity>
+                name="body_template"
+                inputType="multiline"
+                label={i18n.str`Http body`}
+                tooltip={i18n.str`Body template by the webhook`}
+              />
+            </FormProvider>
+
+            <div class="buttons is-right mt-5">
+              {onBack && (
+                <button class="button" onClick={onBack}>
+                  <i18n.Translate>Cancel</i18n.Translate>
+                </button>
+              )}
+              <AsyncButton
+                disabled={hasErrors}
+                data-tooltip={
+                  hasErrors
+                    ? i18n.str`Need to complete marked fields`
+                    : "confirm operation"
+                }
+                onClick={submitForm}
+              >
+                <i18n.Translate>Confirm</i18n.Translate>
+              </AsyncButton>
+            </div>
+          </div>
+          <div class="column" />
+        </div>
+      </section>
+    </div>
+  );
+}
diff --git 
a/packages/auditor-backoffice-ui/src/paths/instance/webhooks/create/index.tsx 
b/packages/auditor-backoffice-ui/src/paths/instance/webhooks/create/index.tsx
new file mode 100644
index 000000000..924e6d9b8
--- /dev/null
+++ 
b/packages/auditor-backoffice-ui/src/paths/instance/webhooks/create/index.tsx
@@ -0,0 +1,61 @@
+/*
+ This file is part of GNU Taler
+ (C) 2021-2023 Taler Systems S.A.
+
+ GNU Taler is free software; you can redistribute it and/or modify it under the
+ terms of the GNU General Public License as published by the Free Software
+ Foundation; either version 3, or (at your option) any later version.
+
+ GNU Taler is distributed in the hope that it will be useful, but WITHOUT ANY
+ WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
+ A PARTICULAR PURPOSE.  See the GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License along with
+ GNU Taler; see the file COPYING.  If not, see <http://www.gnu.org/licenses/>
+ */
+
+/**
+ *
+ * @author Sebastian Javier Marchano (sebasjm)
+ */
+
+import { useTranslationContext } from "@gnu-taler/web-util/browser";
+import { Fragment, h, VNode } from "preact";
+import { useState } from "preact/hooks";
+import { NotificationCard } from "../../../../components/menu/index.js";
+import { MerchantBackend } from "../../../../declaration.js";
+import { useWebhookAPI } from "../../../../hooks/webhooks.js";
+import { Notification } from "../../../../utils/types.js";
+import { CreatePage } from "./CreatePage.js";
+
+export type Entity = MerchantBackend.Webhooks.WebhookAddDetails;
+interface Props {
+  onBack?: () => void;
+  onConfirm: () => void;
+}
+
+export default function CreateWebhook({ onConfirm, onBack }: Props): VNode {
+  const { createWebhook } = useWebhookAPI();
+  const [notif, setNotif] = useState<Notification | undefined>(undefined);
+  const { i18n } = useTranslationContext();
+
+  return (
+    <>
+      <NotificationCard notification={notif} />
+      <CreatePage
+        onBack={onBack}
+        onCreate={(request: MerchantBackend.Webhooks.WebhookAddDetails) => {
+          return createWebhook(request)
+            .then(() => onConfirm())
+            .catch((error) => {
+              setNotif({
+                message: i18n.str`could not inform template`,
+                type: "ERROR",
+                description: error.message,
+              });
+            });
+        }}
+      />
+    </>
+  );
+}
diff --git 
a/packages/auditor-backoffice-ui/src/paths/instance/webhooks/list/List.stories.tsx
 
b/packages/auditor-backoffice-ui/src/paths/instance/webhooks/list/List.stories.tsx
new file mode 100644
index 000000000..702e9ba4a
--- /dev/null
+++ 
b/packages/auditor-backoffice-ui/src/paths/instance/webhooks/list/List.stories.tsx
@@ -0,0 +1,28 @@
+/*
+ This file is part of GNU Taler
+ (C) 2021-2023 Taler Systems S.A.
+
+ GNU Taler is free software; you can redistribute it and/or modify it under the
+ terms of the GNU General Public License as published by the Free Software
+ Foundation; either version 3, or (at your option) any later version.
+
+ GNU Taler is distributed in the hope that it will be useful, but WITHOUT ANY
+ WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
+ A PARTICULAR PURPOSE.  See the GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License along with
+ GNU Taler; see the file COPYING.  If not, see <http://www.gnu.org/licenses/>
+ */
+
+/**
+ *
+ * @author Sebastian Javier Marchano (sebasjm)
+ */
+
+import { FunctionalComponent, h } from "preact";
+import { ListPage as TestedComponent } from "./ListPage.js";
+
+export default {
+  title: "Pages/Templates/List",
+  component: TestedComponent,
+};
diff --git 
a/packages/auditor-backoffice-ui/src/paths/instance/webhooks/list/ListPage.tsx 
b/packages/auditor-backoffice-ui/src/paths/instance/webhooks/list/ListPage.tsx
new file mode 100644
index 000000000..87e221e3c
--- /dev/null
+++ 
b/packages/auditor-backoffice-ui/src/paths/instance/webhooks/list/ListPage.tsx
@@ -0,0 +1,64 @@
+/*
+ This file is part of GNU Taler
+ (C) 2021-2023 Taler Systems S.A.
+
+ GNU Taler is free software; you can redistribute it and/or modify it under the
+ terms of the GNU General Public License as published by the Free Software
+ Foundation; either version 3, or (at your option) any later version.
+
+ GNU Taler is distributed in the hope that it will be useful, but WITHOUT ANY
+ WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
+ A PARTICULAR PURPOSE.  See the GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License along with
+ GNU Taler; see the file COPYING.  If not, see <http://www.gnu.org/licenses/>
+ */
+
+/**
+ *
+ * @author Sebastian Javier Marchano (sebasjm)
+ */
+
+import { h, VNode } from "preact";
+import { MerchantBackend } from "../../../../declaration.js";
+import { useTranslationContext } from "@gnu-taler/web-util/browser";
+import { CardTable } from "./Table.js";
+
+export interface Props {
+  webhooks: MerchantBackend.Webhooks.WebhookEntry[];
+  onLoadMoreBefore?: () => void;
+  onLoadMoreAfter?: () => void;
+  onCreate: () => void;
+  onDelete: (e: MerchantBackend.Webhooks.WebhookEntry) => void;
+  onSelect: (e: MerchantBackend.Webhooks.WebhookEntry) => void;
+}
+
+export function ListPage({
+  webhooks,
+  onCreate,
+  onDelete,
+  onSelect,
+  onLoadMoreBefore,
+  onLoadMoreAfter,
+}: Props): VNode {
+  const form = { payto_uri: "" };
+
+  const { i18n } = useTranslationContext();
+  return (
+    <section class="section is-main-section">
+      <CardTable
+        webhooks={webhooks.map((o) => ({
+          ...o,
+          id: String(o.webhook_id),
+        }))}
+        onCreate={onCreate}
+        onDelete={onDelete}
+        onSelect={onSelect}
+        onLoadMoreBefore={onLoadMoreBefore}
+        hasMoreBefore={!onLoadMoreBefore}
+        onLoadMoreAfter={onLoadMoreAfter}
+        hasMoreAfter={!onLoadMoreAfter}
+      />
+    </section>
+  );
+}
diff --git 
a/packages/auditor-backoffice-ui/src/paths/instance/webhooks/list/Table.tsx 
b/packages/auditor-backoffice-ui/src/paths/instance/webhooks/list/Table.tsx
new file mode 100644
index 000000000..42a179d2c
--- /dev/null
+++ b/packages/auditor-backoffice-ui/src/paths/instance/webhooks/list/Table.tsx
@@ -0,0 +1,218 @@
+/*
+ This file is part of GNU Taler
+ (C) 2021-2023 Taler Systems S.A.
+
+ GNU Taler is free software; you can redistribute it and/or modify it under the
+ terms of the GNU General Public License as published by the Free Software
+ Foundation; either version 3, or (at your option) any later version.
+
+ GNU Taler is distributed in the hope that it will be useful, but WITHOUT ANY
+ WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
+ A PARTICULAR PURPOSE.  See the GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License along with
+ GNU Taler; see the file COPYING.  If not, see <http://www.gnu.org/licenses/>
+ */
+
+/**
+ *
+ * @author Sebastian Javier Marchano (sebasjm)
+ */
+
+import { useTranslationContext } from "@gnu-taler/web-util/browser";
+import { h, VNode } from "preact";
+import { StateUpdater, useState } from "preact/hooks";
+import { MerchantBackend } from "../../../../declaration.js";
+
+type Entity = MerchantBackend.Webhooks.WebhookEntry;
+
+interface Props {
+  webhooks: Entity[];
+  onDelete: (e: Entity) => void;
+  onSelect: (e: Entity) => void;
+  onCreate: () => void;
+  onLoadMoreBefore?: () => void;
+  hasMoreBefore?: boolean;
+  hasMoreAfter?: boolean;
+  onLoadMoreAfter?: () => void;
+}
+
+export function CardTable({
+  webhooks,
+  onCreate,
+  onDelete,
+  onSelect,
+  onLoadMoreAfter,
+  onLoadMoreBefore,
+  hasMoreAfter,
+  hasMoreBefore,
+}: Props): VNode {
+  const [rowSelection, rowSelectionHandler] = useState<string[]>([]);
+
+  const { i18n } = useTranslationContext();
+
+  return (
+    <div class="card has-table">
+      <header class="card-header">
+        <p class="card-header-title">
+          <span class="icon">
+            <i class="mdi mdi-newspaper" />
+          </span>
+          <i18n.Translate>Webhooks</i18n.Translate>
+        </p>
+        <div class="card-header-icon" aria-label="more options">
+          <span
+            class="has-tooltip-left"
+            data-tooltip={i18n.str`add new webhooks`}
+          >
+            <button class="button is-info" type="button" onClick={onCreate}>
+              <span class="icon is-small">
+                <i class="mdi mdi-plus mdi-36px" />
+              </span>
+            </button>
+          </span>
+        </div>
+      </header>
+      <div class="card-content">
+        <div class="b-table has-pagination">
+          <div class="table-wrapper has-mobile-cards">
+            {webhooks.length > 0 ? (
+              <Table
+                instances={webhooks}
+                onDelete={onDelete}
+                onSelect={onSelect}
+                rowSelection={rowSelection}
+                rowSelectionHandler={rowSelectionHandler}
+                onLoadMoreAfter={onLoadMoreAfter}
+                onLoadMoreBefore={onLoadMoreBefore}
+                hasMoreAfter={hasMoreAfter}
+                hasMoreBefore={hasMoreBefore}
+              />
+            ) : (
+              <EmptyTable />
+            )}
+          </div>
+        </div>
+      </div>
+    </div>
+  );
+}
+interface TableProps {
+  rowSelection: string[];
+  instances: Entity[];
+  onDelete: (e: Entity) => void;
+  onSelect: (e: Entity) => void;
+  rowSelectionHandler: StateUpdater<string[]>;
+  onLoadMoreBefore?: () => void;
+  hasMoreBefore?: boolean;
+  hasMoreAfter?: boolean;
+  onLoadMoreAfter?: () => void;
+}
+
+function toggleSelected<T>(id: T): (prev: T[]) => T[] {
+  return (prev: T[]): T[] =>
+    prev.indexOf(id) == -1 ? [...prev, id] : prev.filter((e) => e != id);
+}
+
+function Table({
+  instances,
+  onLoadMoreAfter,
+  onDelete,
+  onSelect,
+  onLoadMoreBefore,
+  hasMoreAfter,
+  hasMoreBefore,
+}: TableProps): VNode {
+  const { i18n } = useTranslationContext();
+  return (
+    <div class="table-container">
+      {hasMoreBefore && (
+        <button
+          class="button is-fullwidth"
+          data-tooltip={i18n.str`load more webhooks before the first one`}
+          onClick={onLoadMoreBefore}
+        >
+          <i18n.Translate>load newer webhooks</i18n.Translate>
+        </button>
+      )}
+      <table class="table is-fullwidth is-striped is-hoverable is-fullwidth">
+        <thead>
+          <tr>
+            <th>
+              <i18n.Translate>ID</i18n.Translate>
+            </th>
+            <th>
+              <i18n.Translate>Event type</i18n.Translate>
+            </th>
+            <th />
+          </tr>
+        </thead>
+        <tbody>
+          {instances.map((i) => {
+            return (
+              <tr key={i.webhook_id}>
+                <td
+                  onClick={(): void => onSelect(i)}
+                  style={{ cursor: "pointer" }}
+                >
+                  {i.webhook_id}
+                </td>
+                <td
+                  onClick={(): void => onSelect(i)}
+                  style={{ cursor: "pointer" }}
+                >
+                  {i.event_type}
+                </td>
+                <td class="is-actions-cell right-sticky">
+                  <div class="buttons is-right">
+                    <button
+                      class="button is-danger is-small has-tooltip-left"
+                      data-tooltip={i18n.str`delete selected webhook from the 
database`}
+                      onClick={() => onDelete(i)}
+                    >
+                      Delete
+                    </button>
+                    {/* <button
+                      class="button is-info is-small has-tooltip-left"
+                      data-tooltip={i18n.str`test webhook`}
+                      onClick={() => onNewOrder(i)}
+                    >
+                      Test
+                    </button> */}
+                  </div>
+                </td>
+              </tr>
+            );
+          })}
+        </tbody>
+      </table>
+      {hasMoreAfter && (
+        <button
+          class="button is-fullwidth"
+          data-tooltip={i18n.str`load more webhooks after the last one`}
+          onClick={onLoadMoreAfter}
+        >
+          <i18n.Translate>load older webhooks</i18n.Translate>
+        </button>
+      )}
+    </div>
+  );
+}
+
+function EmptyTable(): VNode {
+  const { i18n } = useTranslationContext();
+  return (
+    <div class="content has-text-grey has-text-centered">
+      <p>
+        <span class="icon is-large">
+          <i class="mdi mdi-emoticon-sad mdi-48px" />
+        </span>
+      </p>
+      <p>
+        <i18n.Translate>
+          There is no webhooks yet, add more pressing the + sign
+        </i18n.Translate>
+      </p>
+    </div>
+  );
+}
diff --git 
a/packages/auditor-backoffice-ui/src/paths/instance/webhooks/list/index.tsx 
b/packages/auditor-backoffice-ui/src/paths/instance/webhooks/list/index.tsx
new file mode 100644
index 000000000..a6f6f1511
--- /dev/null
+++ b/packages/auditor-backoffice-ui/src/paths/instance/webhooks/list/index.tsx
@@ -0,0 +1,109 @@
+/*
+ This file is part of GNU Taler
+ (C) 2021-2023 Taler Systems S.A.
+
+ GNU Taler is free software; you can redistribute it and/or modify it under the
+ terms of the GNU General Public License as published by the Free Software
+ Foundation; either version 3, or (at your option) any later version.
+
+ GNU Taler is distributed in the hope that it will be useful, but WITHOUT ANY
+ WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
+ A PARTICULAR PURPOSE.  See the GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License along with
+ GNU Taler; see the file COPYING.  If not, see <http://www.gnu.org/licenses/>
+ */
+
+/**
+ *
+ * @author Sebastian Javier Marchano (sebasjm)
+ */
+
+import {
+  ErrorType,
+  HttpError,
+  useTranslationContext,
+} from "@gnu-taler/web-util/browser";
+import { Fragment, h, VNode } from "preact";
+import { useState } from "preact/hooks";
+import { Loading } from "../../../../components/exception/loading.js";
+import { NotificationCard } from "../../../../components/menu/index.js";
+import { MerchantBackend } from "../../../../declaration.js";
+import {
+  useInstanceWebhooks,
+  useWebhookAPI,
+} from "../../../../hooks/webhooks.js";
+import { Notification } from "../../../../utils/types.js";
+import { ListPage } from "./ListPage.js";
+import { HttpStatusCode } from "@gnu-taler/taler-util";
+
+interface Props {
+  onUnauthorized: () => VNode;
+  onLoadError: (error: HttpError<MerchantBackend.ErrorDetail>) => VNode;
+  onNotFound: () => VNode;
+  onCreate: () => void;
+  onSelect: (id: string) => void;
+}
+
+export default function ListWebhooks({
+  onUnauthorized,
+  onLoadError,
+  onCreate,
+  onSelect,
+  onNotFound,
+}: Props): VNode {
+  const [position, setPosition] = useState<string | undefined>(undefined);
+  const { i18n } = useTranslationContext();
+  const [notif, setNotif] = useState<Notification | undefined>(undefined);
+  const { deleteWebhook } = useWebhookAPI();
+  const result = useInstanceWebhooks({ position }, (id) => setPosition(id));
+
+  if (result.loading) return <Loading />;
+  if (!result.ok) {
+    if (
+      result.type === ErrorType.CLIENT &&
+      result.status === HttpStatusCode.Unauthorized
+    )
+      return onUnauthorized();
+    if (
+      result.type === ErrorType.CLIENT &&
+      result.status === HttpStatusCode.NotFound
+    )
+      return onNotFound();
+    return onLoadError(result);
+  }
+
+  return (
+    <Fragment>
+      <NotificationCard notification={notif} />
+
+      <ListPage
+        webhooks={result.data.webhooks}
+        onLoadMoreBefore={
+          result.isReachingStart ? result.loadMorePrev : undefined
+        }
+        onLoadMoreAfter={result.isReachingEnd ? result.loadMore : undefined}
+        onCreate={onCreate}
+        onSelect={(e) => {
+          onSelect(e.webhook_id);
+        }}
+        onDelete={(e: MerchantBackend.Webhooks.WebhookEntry) =>
+          deleteWebhook(e.webhook_id)
+            .then(() =>
+              setNotif({
+                message: i18n.str`webhook delete successfully`,
+                type: "SUCCESS",
+              }),
+            )
+            .catch((error) =>
+              setNotif({
+                message: i18n.str`could not delete the webhook`,
+                type: "ERROR",
+                description: error.message,
+              }),
+            )
+        }
+      />
+    </Fragment>
+  );
+}
diff --git 
a/packages/auditor-backoffice-ui/src/paths/instance/webhooks/update/Update.stories.tsx
 
b/packages/auditor-backoffice-ui/src/paths/instance/webhooks/update/Update.stories.tsx
new file mode 100644
index 000000000..8d07cb31f
--- /dev/null
+++ 
b/packages/auditor-backoffice-ui/src/paths/instance/webhooks/update/Update.stories.tsx
@@ -0,0 +1,32 @@
+/*
+ This file is part of GNU Taler
+ (C) 2021-2023 Taler Systems S.A.
+
+ GNU Taler is free software; you can redistribute it and/or modify it under the
+ terms of the GNU General Public License as published by the Free Software
+ Foundation; either version 3, or (at your option) any later version.
+
+ GNU Taler is distributed in the hope that it will be useful, but WITHOUT ANY
+ WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
+ A PARTICULAR PURPOSE.  See the GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License along with
+ GNU Taler; see the file COPYING.  If not, see <http://www.gnu.org/licenses/>
+ */
+
+/**
+ *
+ * @author Sebastian Javier Marchano (sebasjm)
+ */
+
+import { h, VNode, FunctionalComponent } from "preact";
+import { UpdatePage as TestedComponent } from "./UpdatePage.js";
+
+export default {
+  title: "Pages/Templates/Update",
+  component: TestedComponent,
+  argTypes: {
+    onUpdate: { action: "onUpdate" },
+    onBack: { action: "onBack" },
+  },
+};
diff --git 
a/packages/auditor-backoffice-ui/src/paths/instance/webhooks/update/UpdatePage.tsx
 
b/packages/auditor-backoffice-ui/src/paths/instance/webhooks/update/UpdatePage.tsx
new file mode 100644
index 000000000..76a23b6e5
--- /dev/null
+++ 
b/packages/auditor-backoffice-ui/src/paths/instance/webhooks/update/UpdatePage.tsx
@@ -0,0 +1,146 @@
+/*
+ This file is part of GNU Taler
+ (C) 2021-2023 Taler Systems S.A.
+
+ GNU Taler is free software; you can redistribute it and/or modify it under the
+ terms of the GNU General Public License as published by the Free Software
+ Foundation; either version 3, or (at your option) any later version.
+
+ GNU Taler is distributed in the hope that it will be useful, but WITHOUT ANY
+ WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
+ A PARTICULAR PURPOSE.  See the GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License along with
+ GNU Taler; see the file COPYING.  If not, see <http://www.gnu.org/licenses/>
+ */
+
+/**
+ *
+ * @author Sebastian Javier Marchano (sebasjm)
+ */
+
+import { useTranslationContext } from "@gnu-taler/web-util/browser";
+import { h, VNode } from "preact";
+import { useState } from "preact/hooks";
+import { AsyncButton } from "../../../../components/exception/AsyncButton.js";
+import {
+  FormErrors,
+  FormProvider,
+} from "../../../../components/form/FormProvider.js";
+import { Input } from "../../../../components/form/Input.js";
+import { useBackendContext } from "../../../../context/backend.js";
+import { MerchantBackend, WithId } from "../../../../declaration.js";
+
+type Entity = MerchantBackend.Webhooks.WebhookPatchDetails & WithId;
+
+interface Props {
+  onUpdate: (d: Entity) => Promise<void>;
+  onBack?: () => void;
+  webhook: Entity;
+}
+const validMethod = ["GET", "POST", "PUT", "PATCH", "HEAD"];
+
+export function UpdatePage({ webhook, onUpdate, onBack }: Props): VNode {
+  const { i18n } = useTranslationContext();
+
+  const [state, setState] = useState<Partial<Entity>>(webhook);
+
+  const errors: FormErrors<Entity> = {
+    event_type: !state.event_type ? i18n.str`required` : undefined,
+    http_method: !state.http_method
+      ? i18n.str`required`
+      : !validMethod.includes(state.http_method)
+      ? i18n.str`should be one of '${validMethod.join(", ")}'`
+      : undefined,
+    url: !state.url ? i18n.str`required` : undefined,
+  };
+
+  const hasErrors = Object.keys(errors).some(
+    (k) => (errors as any)[k] !== undefined,
+  );
+
+  const submitForm = () => {
+    if (hasErrors) return Promise.reject();
+    return onUpdate(state as any);
+  };
+
+  return (
+    <div>
+      <section class="section">
+        <section class="hero is-hero-bar">
+          <div class="hero-body">
+            <div class="level">
+              <div class="level-left">
+                <div class="level-item">
+                  <span class="is-size-4">
+                    Webhook: <b>{webhook.id}</b>
+                  </span>
+                </div>
+              </div>
+            </div>
+          </div>
+        </section>
+        <hr />
+
+        <section class="section is-main-section">
+          <div class="columns">
+            <div class="column is-four-fifths">
+              <FormProvider
+                object={state}
+                valueHandler={setState}
+                errors={errors}
+              >
+                <Input<Entity>
+                  name="event_type"
+                  label={i18n.str`Event`}
+                  tooltip={i18n.str`The event of the webhook: why the webhook 
is used`}
+                />
+                <Input<Entity>
+                  name="http_method"
+                  label={i18n.str`Method`}
+                  tooltip={i18n.str`Method used by the webhook`}
+                />
+                <Input<Entity>
+                  name="url"
+                  label={i18n.str`URL`}
+                  tooltip={i18n.str`URL of the webhook where the customer will 
be redirected`}
+                />
+                <Input<Entity>
+                  name="header_template"
+                  label={i18n.str`Header`}
+                  inputType="multiline"
+                  tooltip={i18n.str`Header template of the webhook`}
+                />
+                <Input<Entity>
+                  name="body_template"
+                  inputType="multiline"
+                  label={i18n.str`Body`}
+                  tooltip={i18n.str`Body template by the webhook`}
+                />
+              </FormProvider>
+
+              <div class="buttons is-right mt-5">
+                {onBack && (
+                  <button class="button" onClick={onBack}>
+                    <i18n.Translate>Cancel</i18n.Translate>
+                  </button>
+                )}
+                <AsyncButton
+                  disabled={hasErrors}
+                  data-tooltip={
+                    hasErrors
+                      ? i18n.str`Need to complete marked fields`
+                      : "confirm operation"
+                  }
+                  onClick={submitForm}
+                >
+                  <i18n.Translate>Confirm</i18n.Translate>
+                </AsyncButton>
+              </div>
+            </div>
+          </div>
+        </section>
+      </section>
+    </div>
+  );
+}
diff --git 
a/packages/auditor-backoffice-ui/src/paths/instance/webhooks/update/index.tsx 
b/packages/auditor-backoffice-ui/src/paths/instance/webhooks/update/index.tsx
new file mode 100644
index 000000000..3f723ed87
--- /dev/null
+++ 
b/packages/auditor-backoffice-ui/src/paths/instance/webhooks/update/index.tsx
@@ -0,0 +1,99 @@
+/*
+ This file is part of GNU Taler
+ (C) 2021-2023 Taler Systems S.A.
+
+ GNU Taler is free software; you can redistribute it and/or modify it under the
+ terms of the GNU General Public License as published by the Free Software
+ Foundation; either version 3, or (at your option) any later version.
+
+ GNU Taler is distributed in the hope that it will be useful, but WITHOUT ANY
+ WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
+ A PARTICULAR PURPOSE.  See the GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License along with
+ GNU Taler; see the file COPYING.  If not, see <http://www.gnu.org/licenses/>
+ */
+
+/**
+ *
+ * @author Sebastian Javier Marchano (sebasjm)
+ */
+
+import {
+  ErrorType,
+  HttpError,
+  useTranslationContext,
+} from "@gnu-taler/web-util/browser";
+import { Fragment, h, VNode } from "preact";
+import { useState } from "preact/hooks";
+import { Loading } from "../../../../components/exception/loading.js";
+import { NotificationCard } from "../../../../components/menu/index.js";
+import { MerchantBackend, WithId } from "../../../../declaration.js";
+import {
+  useWebhookAPI,
+  useWebhookDetails,
+} from "../../../../hooks/webhooks.js";
+import { Notification } from "../../../../utils/types.js";
+import { UpdatePage } from "./UpdatePage.js";
+import { HttpStatusCode } from "@gnu-taler/taler-util";
+
+export type Entity = MerchantBackend.Webhooks.WebhookPatchDetails & WithId;
+
+interface Props {
+  onBack?: () => void;
+  onConfirm: () => void;
+  onUnauthorized: () => VNode;
+  onNotFound: () => VNode;
+  onLoadError: (e: HttpError<MerchantBackend.ErrorDetail>) => VNode;
+  tid: string;
+}
+export default function UpdateWebhook({
+  tid,
+  onConfirm,
+  onBack,
+  onUnauthorized,
+  onNotFound,
+  onLoadError,
+}: Props): VNode {
+  const { updateWebhook } = useWebhookAPI();
+  const result = useWebhookDetails(tid);
+  const [notif, setNotif] = useState<Notification | undefined>(undefined);
+
+  const { i18n } = useTranslationContext();
+
+  if (result.loading) return <Loading />;
+  if (!result.ok) {
+    if (
+      result.type === ErrorType.CLIENT &&
+      result.status === HttpStatusCode.Unauthorized
+    )
+      return onUnauthorized();
+    if (
+      result.type === ErrorType.CLIENT &&
+      result.status === HttpStatusCode.NotFound
+    )
+      return onNotFound();
+    return onLoadError(result);
+  }
+
+  return (
+    <Fragment>
+      <NotificationCard notification={notif} />
+      <UpdatePage
+        webhook={{ ...result.data, id: tid }}
+        onBack={onBack}
+        onUpdate={(data) => {
+          return updateWebhook(tid, data)
+            .then(onConfirm)
+            .catch((error) => {
+              setNotif({
+                message: i18n.str`could not update template`,
+                type: "ERROR",
+                description: error.message,
+              });
+            });
+        }}
+      />
+    </Fragment>
+  );
+}
diff --git a/packages/auditor-backoffice-ui/src/paths/login/index.tsx 
b/packages/auditor-backoffice-ui/src/paths/login/index.tsx
new file mode 100644
index 000000000..1c98b7c9b
--- /dev/null
+++ b/packages/auditor-backoffice-ui/src/paths/login/index.tsx
@@ -0,0 +1,202 @@
+/*
+ This file is part of GNU Taler
+ (C) 2021-2023 Taler Systems S.A.
+
+ GNU Taler is free software; you can redistribute it and/or modify it under the
+ terms of the GNU General Public License as published by the Free Software
+ Foundation; either version 3, or (at your option) any later version.
+
+ GNU Taler is distributed in the hope that it will be useful, but WITHOUT ANY
+ WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
+ A PARTICULAR PURPOSE.  See the GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License along with
+ GNU Taler; see the file COPYING.  If not, see <http://www.gnu.org/licenses/>
+ */
+
+/**
+ *
+ * @author Sebastian Javier Marchano (sebasjm)
+ */
+
+import { useTranslationContext } from "@gnu-taler/web-util/browser";
+import { ComponentChildren, h, VNode } from "preact";
+import { useCallback, useEffect, useState } from "preact/hooks";
+import { useBackendContext } from "../../context/backend.js";
+import { useInstanceContext } from "../../context/instance.js";
+import { AccessToken, LoginToken } from "../../declaration.js";
+import { useCredentialsChecker } from "../../hooks/backend.js";
+
+interface Props {
+  onConfirm: (token: LoginToken | undefined) => void;
+}
+
+function normalizeToken(r: string): AccessToken {
+  return `secret-token:${r}` as AccessToken;
+}
+
+export function LoginPage({ onConfirm }: Props): VNode {
+  const { url: backendURL } = useBackendContext();
+  const { admin, id } = useInstanceContext();
+  const { requestNewLoginToken } = useCredentialsChecker();
+  const [token, setToken] = useState("");
+
+  const { i18n } = useTranslationContext();
+
+
+  const doLogin = useCallback(async function doLoginImpl() {
+    const secretToken = normalizeToken(token);
+    const baseUrl = id === undefined ? backendURL : 
`${backendURL}/instances/${id}`
+    const result = await requestNewLoginToken(baseUrl, secretToken);
+    if (result.valid) {
+      const { token, expiration } = result
+      onConfirm({ token, expiration });
+    } else {
+      onConfirm(undefined);
+    }
+  }, [id, token])
+
+  if (admin && id !== "default") {
+    //admin trying to access another instance
+    return (<div class="columns is-centered" style={{ margin: "auto" }}>
+      <div class="column is-two-thirds ">
+        <div class="modal-card" style={{ width: "100%", margin: 0 }}>
+          <header
+            class="modal-card-head"
+            style={{ border: "1px solid", borderBottom: 0 }}
+          >
+            <p class="modal-card-title">{i18n.str`Login required`}</p>
+          </header>
+          <section
+            class="modal-card-body"
+            style={{ border: "1px solid", borderTop: 0, borderBottom: 0 }}
+          >
+            <p>
+              <i18n.Translate>Need the access token for the 
instance.</i18n.Translate>
+            </p>
+            <div class="field is-horizontal">
+              <div class="field-label is-normal">
+                <label class="label">
+                  <i18n.Translate>Access Token</i18n.Translate>
+                </label>
+              </div>
+              <div class="field-body">
+                <div class="field">
+                  <p class="control is-expanded">
+                    <input
+                      class="input"
+                      type="password"
+                      placeholder={"current access token"}
+                      name="token"
+                      onKeyPress={(e) =>
+                        e.keyCode === 13
+                          ? doLogin()
+                          : null
+                      }
+                      value={token}
+                      onInput={(e): void => setToken(e?.currentTarget.value)}
+                    />
+                  </p>
+                </div>
+              </div>
+            </div>
+          </section>
+          <footer
+            class="modal-card-foot "
+            style={{
+              justifyContent: "flex-end",
+              border: "1px solid",
+              borderTop: 0,
+            }}
+          >
+            <AsyncButton
+              onClick={doLogin}
+            >
+              <i18n.Translate>Confirm</i18n.Translate>
+            </AsyncButton>
+          </footer>
+        </div>
+      </div>
+    </div>)
+  }
+
+  return (
+    <div class="columns is-centered" style={{ margin: "auto" }}>
+      <div class="column is-two-thirds ">
+        <div class="modal-card" style={{ width: "100%", margin: 0 }}>
+          <header
+            class="modal-card-head"
+            style={{ border: "1px solid", borderBottom: 0 }}
+          >
+            <p class="modal-card-title">{i18n.str`Login required`}</p>
+          </header>
+          <section
+            class="modal-card-body"
+            style={{ border: "1px solid", borderTop: 0, borderBottom: 0 }}
+          >
+            <i18n.Translate>Please enter your access token.</i18n.Translate>
+
+            <div class="field is-horizontal">
+              <div class="field-label is-normal">
+                <label class="label">
+                  <i18n.Translate>Access Token</i18n.Translate>
+                </label>
+              </div>
+              <div class="field-body">
+                <div class="field">
+                  <p class="control is-expanded">
+                    <input
+                      class="input"
+                      type="password"
+                      placeholder={"current access token"}
+                      name="token"
+                      onKeyPress={(e) =>
+                        e.keyCode === 13
+                          ? doLogin()
+                          : null
+                      }
+                      value={token}
+                      onInput={(e): void => setToken(e?.currentTarget.value)}
+                    />
+                  </p>
+                </div>
+              </div>
+            </div>
+          </section>
+          <footer
+            class="modal-card-foot "
+            style={{
+              justifyContent: "space-between",
+              border: "1px solid",
+              borderTop: 0,
+            }}
+          >
+            <div />
+            <AsyncButton
+              type="is-info"
+              onClick={doLogin}
+            >
+              <i18n.Translate>Confirm</i18n.Translate>
+            </AsyncButton>
+          </footer>
+        </div>
+      </div>
+    </div>
+  );
+}
+
+function AsyncButton({ onClick, disabled, type = "", children }: { type?: 
string, disabled?: boolean, onClick: () => Promise<void>, children: 
ComponentChildren }): VNode {
+  const [running, setRunning] = useState(false)
+  return <button class={"button " + type} disabled={disabled || running} 
onClick={() => {
+    setRunning(true)
+    onClick().then(() => {
+      setRunning(false)
+    }).catch(() => {
+      setRunning(false)
+    })
+  }}>
+    {children}
+  </button>
+}
+
+
diff --git a/packages/auditor-backoffice-ui/src/paths/notfound/index.tsx 
b/packages/auditor-backoffice-ui/src/paths/notfound/index.tsx
new file mode 100644
index 000000000..061a67025
--- /dev/null
+++ b/packages/auditor-backoffice-ui/src/paths/notfound/index.tsx
@@ -0,0 +1,34 @@
+/*
+ This file is part of GNU Taler
+ (C) 2021-2023 Taler Systems S.A.
+
+ GNU Taler is free software; you can redistribute it and/or modify it under the
+ terms of the GNU General Public License as published by the Free Software
+ Foundation; either version 3, or (at your option) any later version.
+
+ GNU Taler is distributed in the hope that it will be useful, but WITHOUT ANY
+ WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
+ A PARTICULAR PURPOSE.  See the GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License along with
+ GNU Taler; see the file COPYING.  If not, see <http://www.gnu.org/licenses/>
+ */
+
+/**
+ *
+ * @author Sebastian Javier Marchano (sebasjm)
+ */
+
+import { h, VNode } from "preact";
+import { Link } from "preact-router";
+
+export default function NotFoundPage(): VNode {
+  return (
+    <div>
+      <p>That page doesn&apos;t exist.</p>
+      <Link href="/">
+        <h4>Back to Home</h4>
+      </Link>
+    </div>
+  );
+}
diff --git a/packages/auditor-backoffice-ui/src/paths/settings/index.tsx 
b/packages/auditor-backoffice-ui/src/paths/settings/index.tsx
new file mode 100644
index 000000000..87bd2fa39
--- /dev/null
+++ b/packages/auditor-backoffice-ui/src/paths/settings/index.tsx
@@ -0,0 +1,112 @@
+import { useLang, useTranslationContext } from "@gnu-taler/web-util/browser";
+import { VNode, h } from "preact";
+import { FormErrors, FormProvider } from 
"../../components/form/FormProvider.js";
+import { InputSelector } from "../../components/form/InputSelector.js";
+import { InputToggle } from "../../components/form/InputToggle.js";
+import { LangSelector } from "../../components/menu/LangSelector.js";
+import { Settings, useSettings } from "../../hooks/useSettings.js";
+
+function getBrowserLang(): string | undefined {
+  if (typeof window === "undefined") return undefined;
+  if (window.navigator.languages) return window.navigator.languages[0];
+  if (window.navigator.language) return window.navigator.language;
+  return undefined;
+}
+
+export function Settings({ onClose }: { onClose?: () => void }): VNode {
+  const { i18n } = useTranslationContext()
+  const borwserLang = getBrowserLang()
+  const { update } = useLang()
+
+  const [value, updateValue] = useSettings()
+  const errors: FormErrors<Settings> = {
+  }
+
+  function valueHandler(s: (d: Partial<Settings>) => Partial<Settings>): void {
+    const next = s(value)
+    const v: Settings = {
+      advanceOrderMode: next.advanceOrderMode ?? false,
+      dateFormat: next.dateFormat ?? "ymd"
+    }
+    updateValue(v)
+  }
+
+  return <div>
+    <section class="section is-main-section">
+      <div class="columns">
+        <div class="column" />
+        <div class="column is-four-fifths">
+          <div>
+
+            <FormProvider<Settings>
+              name="settings"
+              errors={errors}
+              object={value}
+              valueHandler={valueHandler}
+            >
+              <div class="field is-horizontal">
+                <div class="field-label is-normal">
+                  <label class="label">
+                    <i18n.Translate>Language</i18n.Translate>
+                    <span class="icon has-tooltip-right" data-tooltip={"Force 
language setting instance of taking the browser"}>
+                      <i class="mdi mdi-information" />
+                    </span>
+                  </label>
+                </div>
+                <div class="field field-body has-addons is-flex-grow-3">
+                  <LangSelector />
+                  &nbsp;
+                  {borwserLang !== undefined && <button
+                    data-tooltip={i18n.str`generate random secret key`}
+                    class="button is-info mr-2"
+                    onClick={(e) => {
+                      update(borwserLang.substring(0, 2))
+                    }}
+                  >
+                    <i18n.Translate>Set default</i18n.Translate>
+                  </button>}
+                </div>
+              </div>
+              <InputToggle<Settings>
+                label={i18n.str`Advance order creation`}
+                tooltip={i18n.str`Shows more options in the order creation 
form`}
+                name="advanceOrderMode"
+              />
+              <InputSelector<Settings>
+                name="dateFormat"
+                label={i18n.str`Date format`}
+                expand={true}
+                help={
+                  value.dateFormat === "dmy" ? "31/12/2001" : value.dateFormat 
=== "mdy" ? "12/31/2001" : value.dateFormat === "ymd" ? "2001/12/31" : ""
+                }
+                toStr={(e) => {
+                  if (e === "ymd") return "year month day"
+                  if (e === "mdy") return "month day year"
+                  if (e === "dmy") return "day month year"
+                  return "choose one"
+                }}
+                values={[
+                  "ymd",
+                  "mdy",
+                  "dmy",
+                ]}
+                tooltip={i18n.str`how the date is going to be displayed`}
+              />
+            </FormProvider>
+          </div>
+        </div>
+        <div class="column" />
+      </div>
+    </section >
+    {onClose &&
+      <section class="section is-main-section">
+        <button
+          class="button"
+          onClick={onClose}
+        >
+          <i18n.Translate>Close</i18n.Translate>
+        </button>
+      </section>
+    }
+  </div >
+}
\ No newline at end of file
diff --git a/packages/auditor-backoffice-ui/src/schemas/index.ts 
b/packages/auditor-backoffice-ui/src/schemas/index.ts
new file mode 100644
index 000000000..380466e13
--- /dev/null
+++ b/packages/auditor-backoffice-ui/src/schemas/index.ts
@@ -0,0 +1,245 @@
+/*
+ This file is part of GNU Taler
+ (C) 2021-2024 Taler Systems S.A.
+
+ GNU Taler is free software; you can redistribute it and/or modify it under the
+ terms of the GNU General Public License as published by the Free Software
+ Foundation; either version 3, or (at your option) any later version.
+
+ GNU Taler is distributed in the hope that it will be useful, but WITHOUT ANY
+ WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
+ A PARTICULAR PURPOSE.  See the GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License along with
+ GNU Taler; see the file COPYING.  If not, see <http://www.gnu.org/licenses/>
+ */
+
+/**
+ *
+ * @author Sebastian Javier Marchano (sebasjm)
+ */
+
+import { isAfter, isFuture } from "date-fns";
+import * as yup from "yup";
+import { AMOUNT_REGEX, PAYTO_REGEX } from "../utils/constants.js";
+import { Amounts } from "@gnu-taler/taler-util";
+
+yup.setLocale({
+  mixed: {
+    default: "field_invalid",
+  },
+  number: {
+    min: ({ min }: any) => ({ key: "field_too_short", values: { min } }),
+    max: ({ max }: any) => ({ key: "field_too_big", values: { max } }),
+  },
+});
+
+function listOfPayToUrisAreValid(values?: (string | undefined)[]): boolean {
+  return !!values && values.every((v) => v && PAYTO_REGEX.test(v));
+}
+
+function currencyWithAmountIsValid(value?: string): boolean {
+  return !!value && Amounts.parse(value) !== undefined;
+}
+function currencyGreaterThan0(value?: string) {
+  if (value) {
+    try {
+      const [, amount] = value.split(":");
+      const intAmount = parseInt(amount, 10);
+      return intAmount > 0;
+    } catch {
+      return false;
+    }
+  }
+  return true;
+}
+
+export const InstanceSchema = yup.object().shape({
+  id: yup.string().required().meta({ type: "url" }),
+  name: yup.string().required(),
+  auth: yup.object().shape({
+    method: yup.string().matches(/^(external|token)$/),
+    token: yup.string().optional().nullable(),
+  }),
+  payto_uris: yup
+    .array()
+    .of(yup.string())
+    .min(1)
+    .meta({ type: "array" })
+    .test("payto", "{path} is not valid", listOfPayToUrisAreValid),
+  default_max_deposit_fee: yup
+    .string()
+    .required()
+    .test("amount", "the amount is not valid", currencyWithAmountIsValid)
+    .meta({ type: "amount" }),
+  default_max_wire_fee: yup
+    .string()
+    .required()
+    .test("amount", "{path} is not valid", currencyWithAmountIsValid)
+    .meta({ type: "amount" }),
+  default_wire_fee_amortization: yup.number().required(),
+  address: yup
+    .object()
+    .shape({
+      country: yup.string().optional(),
+      address_lines: yup.array().of(yup.string()).max(7).optional(),
+      building_number: yup.string().optional(),
+      building_name: yup.string().optional(),
+      street: yup.string().optional(),
+      post_code: yup.string().optional(),
+      town_location: yup.string().optional(),
+      town: yup.string(),
+      district: yup.string().optional(),
+      country_subdivision: yup.string().optional(),
+    })
+    .meta({ type: "group" }),
+  jurisdiction: yup
+    .object()
+    .shape({
+      country: yup.string().optional(),
+      address_lines: yup.array().of(yup.string()).max(7).optional(),
+      building_number: yup.string().optional(),
+      building_name: yup.string().optional(),
+      street: yup.string().optional(),
+      post_code: yup.string().optional(),
+      town_location: yup.string().optional(),
+      town: yup.string(),
+      district: yup.string().optional(),
+      country_subdivision: yup.string().optional(),
+    })
+    .meta({ type: "group" }),
+  // default_pay_delay: yup.object()
+  //   .shape({ d_us: yup.number() })
+  //   .required()
+  //   .meta({ type: 'duration' }),
+  // .transform(numberToDuration),
+  default_wire_transfer_delay: yup
+    .object()
+    .shape({ d_us: yup.number() })
+    .required()
+    .meta({ type: "duration" }),
+  // .transform(numberToDuration),
+});
+
+export const InstanceUpdateSchema = InstanceSchema.clone().omit(["id"]);
+export const InstanceCreateSchema = InstanceSchema.clone();
+
+export const AuthorizeRewardSchema = yup.object().shape({
+  justification: yup.string().required(),
+  amount: yup
+    .string()
+    .required()
+    .test("amount", "the amount is not valid", currencyWithAmountIsValid)
+    .test("amount_positive", "the amount is not valid", currencyGreaterThan0),
+  next_url: yup.string().required(),
+});
+
+const stringIsValidJSON = (value?: string) => {
+  const p = value?.trim();
+  if (!p) return true;
+  try {
+    JSON.parse(p);
+    return true;
+  } catch {
+    return false;
+  }
+};
+
+export const OrderCreateSchema = yup.object().shape({
+  pricing: yup
+    .object()
+    .required()
+    .shape({
+      summary: yup.string().ensure().required(),
+      order_price: yup
+        .string()
+        .ensure()
+        .required()
+        .test("amount", "the amount is not valid", currencyWithAmountIsValid)
+        .test(
+          "amount_positive",
+          "the amount should be greater than 0",
+          currencyGreaterThan0,
+        ),
+    }),
+  // extra: yup.object().test("extra", "is not a JSON format", 
stringIsValidJSON),
+  payments: yup
+    .object()
+    .required()
+    .shape({
+      refund_deadline: yup
+        .date()
+        .test("future", "should be in the future", (d) =>
+          d ? isFuture(d) : true,
+        ),
+      pay_deadline: yup
+        .date()
+        .test("future", "should be in the future", (d) =>
+          d ? isFuture(d) : true,
+        ),
+      auto_refund_deadline: yup
+        .date()
+        .test("future", "should be in the future", (d) =>
+          d ? isFuture(d) : true,
+        ),
+      delivery_date: yup
+        .date()
+        .test("future", "should be in the future", (d) =>
+          d ? isFuture(d) : true,
+        ),
+    })
+    .test("payment", "dates", (d) => {
+      if (
+        d.pay_deadline &&
+        d.refund_deadline &&
+        isAfter(d.refund_deadline, d.pay_deadline)
+      ) {
+        return new yup.ValidationError(
+          "pay deadline should be greater than refund",
+          "asd",
+          "payments.pay_deadline",
+        );
+      }
+      return true;
+    }),
+});
+
+export const ProductCreateSchema = yup.object().shape({
+  product_id: yup.string().ensure().required(),
+  description: yup.string().required(),
+  unit: yup.string().ensure().required(),
+  price: yup
+    .string()
+    .required()
+    .test("amount", "the amount is not valid", currencyWithAmountIsValid),
+  stock: yup.object({}).optional(),
+  minimum_age: yup.number().optional().min(0),
+});
+
+export const ProductUpdateSchema = yup.object().shape({
+  description: yup.string().required(),
+  price: yup
+    .string()
+    .required()
+    .test("amount", "the amount is not valid", currencyWithAmountIsValid),
+  stock: yup.object({}).optional(),
+  minimum_age: yup.number().optional().min(0),
+});
+
+export const TaxSchema = yup.object().shape({
+  name: yup.string().required().ensure(),
+  tax: yup
+    .string()
+    .required()
+    .test("amount", "the amount is not valid", currencyWithAmountIsValid),
+});
+
+export const NonInventoryProductSchema = yup.object().shape({
+  quantity: yup.number().required().positive(),
+  description: yup.string().required(),
+  unit: yup.string().ensure().required(),
+  price: yup
+    .string()
+    .required()
+    .test("amount", "the amount is not valid", currencyWithAmountIsValid),
+});
diff --git a/packages/auditor-backoffice-ui/src/scss/DurationPicker.scss 
b/packages/auditor-backoffice-ui/src/scss/DurationPicker.scss
new file mode 100644
index 000000000..aa75b9916
--- /dev/null
+++ b/packages/auditor-backoffice-ui/src/scss/DurationPicker.scss
@@ -0,0 +1,70 @@
+.rdp-picker {
+  display: flex;
+  height: 175px;
+}
+
+@media (max-width: 400px) {
+  .rdp-picker {
+    width: 250px;
+  }
+}
+
+.rdp-masked-div {
+  overflow: hidden;
+  height: 175px;
+  position: relative;
+}
+
+.rdp-column-container {
+  flex-grow: 1;
+  display: inline-block;
+}
+
+.rdp-column {
+  position: absolute;
+  z-index: 0;
+  width: 100%;
+}
+
+.rdp-reticule {
+  border: 0;
+  border-top: 2px solid rgba(109, 202, 236, 1);
+  height: 2px;
+  position: absolute;
+  width: 80%;
+  margin: 0;
+  z-index: 100;
+  left: 50%;
+  -webkit-transform: translateX(-50%);
+  transform: translateX(-50%);
+}
+
+.rdp-text-overlay {
+  position: absolute;
+  display: flex;
+  align-items: center;
+  justify-content: center;
+  height: 35px;
+  font-size: 20px;
+  left: 50%;
+  -webkit-transform: translateX(-50%);
+  transform: translateX(-50%);
+}
+
+.rdp-cell div {
+  font-size: 17px;
+  color: gray;
+  font-style: italic;
+}
+
+.rdp-cell {
+  display: flex;
+  align-items: center;
+  justify-content: center;
+  height: 35px;
+  font-size: 18px;
+}
+
+.rdp-center {
+  font-size: 25px;
+}
diff --git a/packages/auditor-backoffice-ui/src/scss/_aside.scss 
b/packages/auditor-backoffice-ui/src/scss/_aside.scss
new file mode 100644
index 000000000..e0922093b
--- /dev/null
+++ b/packages/auditor-backoffice-ui/src/scss/_aside.scss
@@ -0,0 +1,181 @@
+/*
+ This file is part of GNU Taler
+ (C) 2021-2023 Taler Systems S.A.
+
+ GNU Taler is free software; you can redistribute it and/or modify it under the
+ terms of the GNU General Public License as published by the Free Software
+ Foundation; either version 3, or (at your option) any later version.
+
+ GNU Taler is distributed in the hope that it will be useful, but WITHOUT ANY
+ WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
+ A PARTICULAR PURPOSE.  See the GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License along with
+ GNU Taler; see the file COPYING.  If not, see <http://www.gnu.org/licenses/>
+ */
+
+/**
+ *
+ * @author Sebastian Javier Marchano (sebasjm)
+ */
+
+@include desktop {
+  html {
+    &.has-aside-left {
+      &.has-aside-expanded {
+        nav.navbar,
+        body {
+          padding-left: $aside-width;
+        }
+      }
+      aside.is-placed-left {
+        display: block;
+      }
+    }
+  }
+
+  aside.aside.is-expanded {
+    width: $aside-width;
+
+    .menu-list {
+      @include icon-with-update-mark($aside-icon-width);
+
+      span.menu-item-label {
+        display: inline-block;
+      }
+
+      li.is-active {
+        ul {
+          display: block;
+        }
+      }
+    }
+  }
+}
+
+aside.aside {
+  display: none;
+  position: fixed;
+  top: 0;
+  left: 0;
+  z-index: 40;
+  height: 100vh;
+  padding: 0;
+  box-shadow: $aside-box-shadow;
+  background: $aside-background-color;
+
+  .aside-tools {
+    display: flex;
+    flex-direction: row;
+    width: 100%;
+    background-color: $aside-tools-background-color;
+    color: $aside-tools-color;
+    line-height: $navbar-height;
+    height: $navbar-height;
+    padding-left: $default-padding * 0.5;
+    flex: 1;
+
+    .icon {
+      margin-right: $default-padding * 0.5;
+    }
+  }
+
+  .menu-list {
+    li {
+      a {
+        &.has-dropdown-icon {
+          position: relative;
+          padding-right: $aside-icon-width;
+
+          .dropdown-icon {
+            position: absolute;
+            top: $size-base * 0.5;
+            right: 0;
+          }
+        }
+      }
+      ul {
+        display: none;
+        border-left: 0;
+        background-color: darken($base-color, 2.5%);
+        padding-left: 0;
+        margin: 0 0 $default-padding * 0.5;
+
+        li {
+          a {
+            padding: $default-padding * 0.5 0 $default-padding * 0.5
+              $default-padding * 0.5;
+            font-size: $aside-submenu-font-size;
+
+            &.has-icon {
+              padding-left: 0;
+            }
+            &.is-active {
+              &:not(:hover) {
+                background: transparent;
+              }
+            }
+          }
+        }
+      }
+    }
+  }
+
+  .menu-label {
+    padding: 0 $default-padding * 0.5;
+    margin-top: $default-padding * 0.5;
+    margin-bottom: $default-padding * 0.5;
+  }
+}
+
+@include touch {
+  nav.navbar {
+    @include transition(margin-left);
+  }
+  aside.aside {
+    @include transition(left);
+  }
+  html.has-aside-mobile-transition {
+    body {
+      overflow-x: hidden;
+    }
+    body,
+    nav.navbar {
+      width: 100vw;
+    }
+    aside.aside {
+      width: $aside-mobile-width;
+      display: block;
+      left: $aside-mobile-width * -1;
+
+      .image {
+        img {
+          max-width: $aside-mobile-width * 0.33;
+        }
+      }
+
+      .menu-list {
+        li.is-active {
+          ul {
+            display: block;
+          }
+        }
+        a {
+          @include icon-with-update-mark($aside-icon-width);
+
+          span.menu-item-label {
+            display: inline-block;
+          }
+        }
+      }
+    }
+  }
+  div.has-aside-mobile-expanded {
+    nav.navbar {
+      margin-left: $aside-mobile-width;
+    }
+    aside.aside {
+      left: 0;
+    }
+  }
+}
diff --git a/packages/auditor-backoffice-ui/src/scss/_card.scss 
b/packages/auditor-backoffice-ui/src/scss/_card.scss
new file mode 100644
index 000000000..62db7f457
--- /dev/null
+++ b/packages/auditor-backoffice-ui/src/scss/_card.scss
@@ -0,0 +1,69 @@
+/*
+ This file is part of GNU Taler
+ (C) 2021-2023 Taler Systems S.A.
+
+ GNU Taler is free software; you can redistribute it and/or modify it under the
+ terms of the GNU General Public License as published by the Free Software
+ Foundation; either version 3, or (at your option) any later version.
+
+ GNU Taler is distributed in the hope that it will be useful, but WITHOUT ANY
+ WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
+ A PARTICULAR PURPOSE.  See the GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License along with
+ GNU Taler; see the file COPYING.  If not, see <http://www.gnu.org/licenses/>
+ */
+
+/**
+ *
+ * @author Sebastian Javier Marchano (sebasjm)
+ */
+
+.card:not(:last-child) {
+  margin-bottom: $default-padding;
+}
+
+.card {
+  border-radius: $radius-large;
+  border: $card-border;
+
+  &.has-table {
+    .card-content {
+      padding: 0;
+    }
+    .b-table {
+      border-radius: $radius-large;
+      overflow: hidden;
+    }
+  }
+
+  &.is-card-widget {
+    .card-content {
+      padding: $default-padding * 0.5;
+    }
+  }
+
+  .card-header {
+    border-bottom: 1px solid $base-color-light;
+  }
+
+  .card-content {
+    hr {
+      margin-left: $card-content-padding * -1;
+      margin-right: $card-content-padding * -1;
+    }
+  }
+
+  .is-widget-icon {
+    .icon {
+      width: 5rem;
+      height: 5rem;
+    }
+  }
+
+  .is-widget-label {
+    .subtitle {
+      color: $grey;
+    }
+  }
+}
diff --git a/packages/auditor-backoffice-ui/src/scss/_custom-calendar.scss 
b/packages/auditor-backoffice-ui/src/scss/_custom-calendar.scss
new file mode 100644
index 000000000..34c40092b
--- /dev/null
+++ b/packages/auditor-backoffice-ui/src/scss/_custom-calendar.scss
@@ -0,0 +1,259 @@
+/*
+ This file is part of GNU Taler
+ (C) 2021-2023 Taler Systems S.A.
+
+ GNU Taler is free software; you can redistribute it and/or modify it under the
+ terms of the GNU General Public License as published by the Free Software
+ Foundation; either version 3, or (at your option) any later version.
+
+ GNU Taler is distributed in the hope that it will be useful, but WITHOUT ANY
+ WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
+ A PARTICULAR PURPOSE.  See the GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License along with
+ GNU Taler; see the file COPYING.  If not, see <http://www.gnu.org/licenses/>
+ */
+
+:root {
+  --primary-color: #3298dc;
+
+  --primary-text-color-dark: rgba(0, 0, 0, 0.87);
+  --secondary-text-color-dark: rgba(0, 0, 0, 0.57);
+  --disabled-text-color-dark: rgba(0, 0, 0, 0.13);
+
+  --primary-text-color-light: rgba(255, 255, 255, 0.87);
+  --secondary-text-color-light: rgba(255, 255, 255, 0.57);
+  --disabled-text-color-light: rgba(255, 255, 255, 0.13);
+
+  --font-stack: "Roboto", "Helvetica Neue", Helvetica, Arial, sans-serif;
+
+  --primary-card-color: #fff;
+  --primary-background-color: #f2f2f2;
+
+  --box-shadow-lvl-1: 0 1px 3px rgba(0, 0, 0, 0.12),
+    0 1px 2px rgba(0, 0, 0, 0.24);
+  --box-shadow-lvl-2: 0 3px 6px rgba(0, 0, 0, 0.16),
+    0 3px 6px rgba(0, 0, 0, 0.23);
+  --box-shadow-lvl-3: 0 10px 20px rgba(0, 0, 0, 0.19),
+    0 6px 6px rgba(0, 0, 0, 0.23);
+  --box-shadow-lvl-4: 0 14px 28px rgba(0, 0, 0, 0.25),
+    0 10px 10px rgba(0, 0, 0, 0.22);
+}
+
+.datePicker {
+  text-align: left;
+  background: var(--primary-card-color);
+  border-radius: 3px;
+  z-index: 200;
+  position: fixed;
+  height: auto;
+  max-height: 90vh;
+  width: 90vw;
+  max-width: 448px;
+  transform-origin: top left;
+  transition: transform 0.22s ease-in-out, opacity 0.22s ease-in-out;
+  top: 50%;
+  left: 50%;
+  opacity: 0;
+  transform: scale(0) translate(-50%, -50%);
+  user-select: none;
+
+  &.datePicker--opened {
+    opacity: 1;
+    transform: scale(1) translate(-50%, -50%);
+  }
+
+  .datePicker--titles {
+    border-top-left-radius: 3px;
+    border-top-right-radius: 3px;
+    padding: 24px;
+    height: 100px;
+    background: var(--primary-color);
+
+    h2,
+    h3 {
+      cursor: pointer;
+      color: #fff;
+      line-height: 1;
+      padding: 0;
+      margin: 0;
+      font-size: 32px;
+    }
+
+    h3 {
+      color: rgba(255, 255, 255, 0.57);
+      font-size: 18px;
+      padding-bottom: 2px;
+    }
+  }
+
+  nav {
+    padding: 20px;
+    height: 56px;
+
+    h4 {
+      width: calc(100% - 60px);
+      text-align: center;
+      display: inline-block;
+      padding: 0;
+      font-size: 14px;
+      line-height: 24px;
+      margin: 0;
+      position: relative;
+      top: -9px;
+      color: var(--primary-text-color);
+    }
+
+    i {
+      cursor: pointer;
+      color: var(--secondary-text-color);
+      font-size: 26px;
+      user-select: none;
+      border-radius: 50%;
+
+      &:hover {
+        background: var(--disabled-text-color-dark);
+      }
+    }
+  }
+
+  .datePicker--scroll {
+    overflow-y: auto;
+    max-height: calc(90vh - 56px - 100px);
+  }
+
+  .datePicker--calendar {
+    padding: 0 20px;
+
+    .datePicker--dayNames {
+      width: 100%;
+      display: grid;
+      text-align: center;
+
+      // there's probably a better way to do this, but wanted to try out CSS 
grid
+      grid-template-columns:
+        calc(100% / 7) calc(100% / 7) calc(100% / 7) calc(100% / 7)
+        calc(100% / 7) calc(100% / 7) calc(100% / 7);
+
+      span {
+        color: var(--secondary-text-color-dark);
+        font-size: 14px;
+        line-height: 42px;
+        display: inline-grid;
+      }
+    }
+
+    .datePicker--days {
+      width: 100%;
+      display: grid;
+      text-align: center;
+      grid-template-columns:
+        calc(100% / 7) calc(100% / 7) calc(100% / 7) calc(100% / 7)
+        calc(100% / 7) calc(100% / 7) calc(100% / 7);
+
+      span {
+        color: var(--primary-text-color-dark);
+        line-height: 42px;
+        font-size: 14px;
+        display: inline-grid;
+        transition: color 0.22s;
+        height: 42px;
+        position: relative;
+        cursor: pointer;
+        user-select: none;
+        border-radius: 50%;
+
+        &::before {
+          content: "";
+          position: absolute;
+          z-index: -1;
+          height: 42px;
+          width: 42px;
+          left: calc(50% - 21px);
+          background: var(--primary-color);
+          border-radius: 50%;
+          transition: transform 0.22s, opacity 0.22s;
+          transform: scale(0);
+          opacity: 0;
+        }
+
+        &[disabled="true"] {
+          cursor: unset;
+        }
+
+        &.datePicker--today {
+          font-weight: 700;
+        }
+
+        &.datePicker--selected {
+          color: rgba(255, 255, 255, 0.87);
+
+          &:before {
+            transform: scale(1);
+            opacity: 1;
+          }
+        }
+      }
+    }
+  }
+
+  .datePicker--selectYear {
+    padding: 0 20px;
+    display: block;
+    width: 100%;
+    text-align: center;
+    max-height: 362px;
+
+    span {
+      display: block;
+      width: 100%;
+      font-size: 24px;
+      margin: 20px auto;
+      cursor: pointer;
+
+      &.selected {
+        font-size: 42px;
+        color: var(--primary-color);
+      }
+    }
+  }
+
+  div.datePicker--actions {
+    width: 100%;
+    padding: 8px;
+    text-align: right;
+
+    button {
+      margin-bottom: 0;
+      font-size: 15px;
+      cursor: pointer;
+      color: var(--primary-text-color);
+      border: none;
+      margin-left: 8px;
+      min-width: 64px;
+      line-height: 36px;
+      background-color: transparent;
+      appearance: none;
+      padding: 0 16px;
+      border-radius: 3px;
+      transition: background-color 0.13s;
+
+      &:hover,
+      &:focus {
+        outline: none;
+        background-color: var(--disabled-text-color-dark);
+      }
+    }
+  }
+}
+
+.datePicker--background {
+  z-index: 199;
+  position: fixed;
+  top: 0;
+  left: 0;
+  bottom: 0;
+  right: 0;
+  background: rgba(0, 0, 0, 0.52);
+  animation: fadeIn 0.22s forwards;
+}
diff --git a/packages/auditor-backoffice-ui/src/scss/_footer.scss 
b/packages/auditor-backoffice-ui/src/scss/_footer.scss
new file mode 100644
index 000000000..5855af742
--- /dev/null
+++ b/packages/auditor-backoffice-ui/src/scss/_footer.scss
@@ -0,0 +1,35 @@
+/*
+ This file is part of GNU Taler
+ (C) 2021-2023 Taler Systems S.A.
+
+ GNU Taler is free software; you can redistribute it and/or modify it under the
+ terms of the GNU General Public License as published by the Free Software
+ Foundation; either version 3, or (at your option) any later version.
+
+ GNU Taler is distributed in the hope that it will be useful, but WITHOUT ANY
+ WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
+ A PARTICULAR PURPOSE.  See the GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License along with
+ GNU Taler; see the file COPYING.  If not, see <http://www.gnu.org/licenses/>
+ */
+
+/**
+ *
+ * @author Sebastian Javier Marchano (sebasjm)
+ */
+
+footer.footer {
+  .logo {
+    img {
+      width: auto;
+      height: $footer-logo-height;
+    }
+  }
+}
+
+@include mobile {
+  .footer-copyright {
+    text-align: center;
+  }
+}
diff --git a/packages/auditor-backoffice-ui/src/scss/_form.scss 
b/packages/auditor-backoffice-ui/src/scss/_form.scss
new file mode 100644
index 000000000..bd28a17cf
--- /dev/null
+++ b/packages/auditor-backoffice-ui/src/scss/_form.scss
@@ -0,0 +1,71 @@
+/*
+ This file is part of GNU Taler
+ (C) 2021-2023 Taler Systems S.A.
+
+ GNU Taler is free software; you can redistribute it and/or modify it under the
+ terms of the GNU General Public License as published by the Free Software
+ Foundation; either version 3, or (at your option) any later version.
+
+ GNU Taler is distributed in the hope that it will be useful, but WITHOUT ANY
+ WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
+ A PARTICULAR PURPOSE.  See the GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License along with
+ GNU Taler; see the file COPYING.  If not, see <http://www.gnu.org/licenses/>
+ */
+
+/**
+ *
+ * @author Sebastian Javier Marchano (sebasjm)
+ */
+
+.field {
+  &.has-check {
+    .field-body {
+      margin-top: $default-padding * 0.125;
+    }
+  }
+  .control {
+    .mdi-24px.mdi-set,
+    .mdi-24px.mdi:before {
+      font-size: inherit;
+    }
+  }
+}
+.upload {
+  .upload-draggable {
+    display: block;
+  }
+}
+
+.input,
+.textarea,
+select {
+  box-shadow: none;
+
+  &:focus,
+  &:active {
+    box-shadow: none !important;
+  }
+}
+
+.switch input[type="checkbox"] + .check:before {
+  box-shadow: none;
+}
+
+.switch,
+.b-checkbox.checkbox {
+  input[type="checkbox"] {
+    &:focus + .check,
+    &:focus:checked + .check {
+      box-shadow: none !important;
+    }
+  }
+}
+
+.b-checkbox.checkbox input[type="checkbox"],
+.b-radio.radio input[type="radio"] {
+  & + .check {
+    border: $checkbox-border;
+  }
+}
diff --git a/packages/auditor-backoffice-ui/src/scss/_hero-bar.scss 
b/packages/auditor-backoffice-ui/src/scss/_hero-bar.scss
new file mode 100644
index 000000000..0276468d7
--- /dev/null
+++ b/packages/auditor-backoffice-ui/src/scss/_hero-bar.scss
@@ -0,0 +1,55 @@
+/*
+ This file is part of GNU Taler
+ (C) 2021-2023 Taler Systems S.A.
+
+ GNU Taler is free software; you can redistribute it and/or modify it under the
+ terms of the GNU General Public License as published by the Free Software
+ Foundation; either version 3, or (at your option) any later version.
+
+ GNU Taler is distributed in the hope that it will be useful, but WITHOUT ANY
+ WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
+ A PARTICULAR PURPOSE.  See the GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License along with
+ GNU Taler; see the file COPYING.  If not, see <http://www.gnu.org/licenses/>
+ */
+
+/**
+ *
+ * @author Sebastian Javier Marchano (sebasjm)
+ */
+
+section.hero.is-hero-bar {
+  background-color: $hero-bar-background;
+  border-bottom: $light-border;
+
+  .hero-body {
+    padding: $default-padding;
+
+    .level-item {
+      &.is-hero-avatar-item {
+        margin-right: $default-padding;
+      }
+
+      > div > .level {
+        margin-bottom: $default-padding * 0.5;
+      }
+
+      .subtitle + p {
+        margin-top: $default-padding * 0.5;
+      }
+    }
+
+    .button {
+      &.is-hero-button {
+        background-color: rgba($white, 0.5);
+        font-weight: 300;
+        @include transition(background-color);
+
+        &:hover {
+          background-color: $white;
+        }
+      }
+    }
+  }
+}
diff --git a/packages/auditor-backoffice-ui/src/scss/_loading.scss 
b/packages/auditor-backoffice-ui/src/scss/_loading.scss
new file mode 100644
index 000000000..d88d8c355
--- /dev/null
+++ b/packages/auditor-backoffice-ui/src/scss/_loading.scss
@@ -0,0 +1,51 @@
+/*
+ This file is part of GNU Taler
+ (C) 2021-2023 Taler Systems S.A.
+
+ GNU Taler is free software; you can redistribute it and/or modify it under the
+ terms of the GNU General Public License as published by the Free Software
+ Foundation; either version 3, or (at your option) any later version.
+
+ GNU Taler is distributed in the hope that it will be useful, but WITHOUT ANY
+ WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
+ A PARTICULAR PURPOSE.  See the GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License along with
+ GNU Taler; see the file COPYING.  If not, see <http://www.gnu.org/licenses/>
+ */
+
+.lds-ring {
+  display: inline-block;
+  position: relative;
+  width: 80px;
+  height: 80px;
+}
+.lds-ring div {
+  box-sizing: border-box;
+  display: block;
+  position: absolute;
+  width: 64px;
+  height: 64px;
+  margin: 8px;
+  border: 8px solid black;
+  border-radius: 50%;
+  animation: lds-ring 1.2s cubic-bezier(0.5, 0, 0.5, 1) infinite;
+  border-color: black transparent transparent transparent;
+}
+.lds-ring div:nth-child(1) {
+  animation-delay: -0.45s;
+}
+.lds-ring div:nth-child(2) {
+  animation-delay: -0.3s;
+}
+.lds-ring div:nth-child(3) {
+  animation-delay: -0.15s;
+}
+@keyframes lds-ring {
+  0% {
+    transform: rotate(0deg);
+  }
+  100% {
+    transform: rotate(360deg);
+  }
+}
diff --git a/packages/auditor-backoffice-ui/src/scss/_main-section.scss 
b/packages/auditor-backoffice-ui/src/scss/_main-section.scss
new file mode 100644
index 000000000..5a8b20ba0
--- /dev/null
+++ b/packages/auditor-backoffice-ui/src/scss/_main-section.scss
@@ -0,0 +1,24 @@
+/*
+ This file is part of GNU Taler
+ (C) 2021-2023 Taler Systems S.A.
+
+ GNU Taler is free software; you can redistribute it and/or modify it under the
+ terms of the GNU General Public License as published by the Free Software
+ Foundation; either version 3, or (at your option) any later version.
+
+ GNU Taler is distributed in the hope that it will be useful, but WITHOUT ANY
+ WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
+ A PARTICULAR PURPOSE.  See the GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License along with
+ GNU Taler; see the file COPYING.  If not, see <http://www.gnu.org/licenses/>
+ */
+
+/**
+ *
+ * @author Sebastian Javier Marchano (sebasjm)
+ */
+
+section.section.is-main-section {
+  padding-top: $default-padding;
+}
diff --git a/packages/auditor-backoffice-ui/src/scss/_misc.scss 
b/packages/auditor-backoffice-ui/src/scss/_misc.scss
new file mode 100644
index 000000000..045d087e2
--- /dev/null
+++ b/packages/auditor-backoffice-ui/src/scss/_misc.scss
@@ -0,0 +1,50 @@
+/*
+ This file is part of GNU Taler
+ (C) 2021-2023 Taler Systems S.A.
+
+ GNU Taler is free software; you can redistribute it and/or modify it under the
+ terms of the GNU General Public License as published by the Free Software
+ Foundation; either version 3, or (at your option) any later version.
+
+ GNU Taler is distributed in the hope that it will be useful, but WITHOUT ANY
+ WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
+ A PARTICULAR PURPOSE.  See the GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License along with
+ GNU Taler; see the file COPYING.  If not, see <http://www.gnu.org/licenses/>
+ */
+
+/**
+ *
+ * @author Sebastian Javier Marchano (sebasjm)
+ */
+
+.is-user-avatar {
+  &.has-max-width {
+    max-width: $size-base * 7;
+  }
+
+  &.is-aligned-center {
+    margin: 0 auto;
+  }
+
+  img {
+    margin: 0 auto;
+    border-radius: $radius-rounded;
+  }
+}
+
+.icon.has-update-mark {
+  position: relative;
+
+  &:after {
+    content: "";
+    width: $icon-update-mark-size;
+    height: $icon-update-mark-size;
+    position: absolute;
+    top: 1px;
+    right: 1px;
+    background-color: $icon-update-mark-color;
+    border-radius: $radius-rounded;
+  }
+}
diff --git a/packages/auditor-backoffice-ui/src/scss/_mixins.scss 
b/packages/auditor-backoffice-ui/src/scss/_mixins.scss
new file mode 100644
index 000000000..f119ec68a
--- /dev/null
+++ b/packages/auditor-backoffice-ui/src/scss/_mixins.scss
@@ -0,0 +1,34 @@
+/*
+ This file is part of GNU Taler
+ (C) 2022 Taler Systems S.A.
+
+ GNU Taler is free software; you can redistribute it and/or modify it under the
+ terms of the GNU General Public License as published by the Free Software
+ Foundation; either version 3, or (at your option) any later version.
+
+ GNU Taler is distributed in the hope that it will be useful, but WITHOUT ANY
+ WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
+ A PARTICULAR PURPOSE.  See the GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License along with
+ GNU Taler; see the file COPYING.  If not, see <http://www.gnu.org/licenses/>
+ */
+
+/**
+ *
+ * @author Sebastian Javier Marchano (sebasjm)
+ */
+
+@mixin transition($t) {
+  transition: $t 250ms ease-in-out 50ms;
+}
+
+@mixin icon-with-update-mark($icon-base-width) {
+  .icon {
+    width: $icon-base-width;
+
+    &.has-update-mark:after {
+      right: calc($icon-base-width / 2) - 0.85;
+    }
+  }
+}
diff --git a/packages/auditor-backoffice-ui/src/scss/_modal.scss 
b/packages/auditor-backoffice-ui/src/scss/_modal.scss
new file mode 100644
index 000000000..b2bfd3e9e
--- /dev/null
+++ b/packages/auditor-backoffice-ui/src/scss/_modal.scss
@@ -0,0 +1,35 @@
+/*
+ This file is part of GNU Taler
+ (C) 2021-2023 Taler Systems S.A.
+
+ GNU Taler is free software; you can redistribute it and/or modify it under the
+ terms of the GNU General Public License as published by the Free Software
+ Foundation; either version 3, or (at your option) any later version.
+
+ GNU Taler is distributed in the hope that it will be useful, but WITHOUT ANY
+ WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
+ A PARTICULAR PURPOSE.  See the GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License along with
+ GNU Taler; see the file COPYING.  If not, see <http://www.gnu.org/licenses/>
+ */
+
+/**
+ *
+ * @author Sebastian Javier Marchano (sebasjm)
+ */
+
+.modal-card {
+  width: $modal-card-width;
+}
+
+.modal-card-foot {
+  background-color: $modal-card-foot-background-color;
+}
+
+@include mobile {
+  .modal .animation-content .modal-card {
+    width: $modal-card-width-mobile;
+    margin: 0 auto;
+  }
+}
diff --git a/packages/auditor-backoffice-ui/src/scss/_nav-bar.scss 
b/packages/auditor-backoffice-ui/src/scss/_nav-bar.scss
new file mode 100644
index 000000000..406e0392f
--- /dev/null
+++ b/packages/auditor-backoffice-ui/src/scss/_nav-bar.scss
@@ -0,0 +1,144 @@
+/*
+ This file is part of GNU Taler
+ (C) 2021-2023 Taler Systems S.A.
+
+ GNU Taler is free software; you can redistribute it and/or modify it under the
+ terms of the GNU General Public License as published by the Free Software
+ Foundation; either version 3, or (at your option) any later version.
+
+ GNU Taler is distributed in the hope that it will be useful, but WITHOUT ANY
+ WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
+ A PARTICULAR PURPOSE.  See the GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License along with
+ GNU Taler; see the file COPYING.  If not, see <http://www.gnu.org/licenses/>
+ */
+
+/**
+ *
+ * @author Sebastian Javier Marchano (sebasjm)
+ */
+
+nav.navbar {
+  box-shadow: $navbar-box-shadow;
+
+  .navbar-item {
+    &.has-user-avatar {
+      .is-user-avatar {
+        margin-right: $default-padding * 0.5;
+        display: inline-flex;
+        width: $navbar-avatar-size;
+        height: $navbar-avatar-size;
+      }
+    }
+
+    &.has-divider {
+      border-right: $navbar-divider-border;
+    }
+
+    &.no-left-space {
+      padding-left: 0;
+    }
+
+    &.has-dropdown {
+      padding-right: 0;
+      padding-left: 0;
+
+      .navbar-link {
+        padding-right: $navbar-item-h-padding;
+        padding-left: $navbar-item-h-padding;
+      }
+    }
+
+    &.has-control {
+      padding-top: 0;
+      padding-bottom: 0;
+    }
+
+    .control {
+      .input {
+        color: $navbar-input-color;
+        border: 0;
+        box-shadow: none;
+        background: transparent;
+
+        &::placeholder {
+          color: $navbar-input-placeholder-color;
+        }
+      }
+    }
+  }
+}
+
+@include touch {
+  nav.navbar {
+    display: flex;
+    padding-right: 0;
+
+    .navbar-brand {
+      flex: 1;
+
+      &.is-right {
+        flex: none;
+      }
+    }
+
+    .navbar-item {
+      &.no-left-space-touch {
+        padding-left: 0;
+      }
+    }
+
+    .navbar-menu {
+      position: absolute;
+      width: 100vw;
+      padding-top: 0;
+      top: $navbar-height;
+      left: 0;
+
+      .navbar-item {
+        .icon:first-child {
+          margin-right: $default-padding * 0.5;
+        }
+
+        &.has-dropdown {
+          > .navbar-link {
+            background-color: $white-ter;
+            .icon:last-child {
+              display: none;
+            }
+          }
+        }
+
+        &.has-user-avatar {
+          > .navbar-link {
+            display: flex;
+            align-items: center;
+            padding-top: $default-padding * 0.5;
+            padding-bottom: $default-padding * 0.5;
+          }
+        }
+      }
+    }
+  }
+}
+
+@include desktop {
+  nav.navbar {
+    .navbar-item {
+      padding-right: $navbar-item-h-padding;
+      padding-left: $navbar-item-h-padding;
+
+      &:not(.is-desktop-icon-only) {
+        .icon:first-child {
+          margin-right: $default-padding * 0.5;
+        }
+      }
+      &.is-desktop-icon-only {
+        span:not(.icon) {
+          display: none;
+        }
+      }
+    }
+  }
+}
diff --git a/packages/auditor-backoffice-ui/src/scss/_table.scss 
b/packages/auditor-backoffice-ui/src/scss/_table.scss
new file mode 100644
index 000000000..e4fbfc7b3
--- /dev/null
+++ b/packages/auditor-backoffice-ui/src/scss/_table.scss
@@ -0,0 +1,179 @@
+/*
+ This file is part of GNU Taler
+ (C) 2021-2023 Taler Systems S.A.
+
+ GNU Taler is free software; you can redistribute it and/or modify it under the
+ terms of the GNU General Public License as published by the Free Software
+ Foundation; either version 3, or (at your option) any later version.
+
+ GNU Taler is distributed in the hope that it will be useful, but WITHOUT ANY
+ WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
+ A PARTICULAR PURPOSE.  See the GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License along with
+ GNU Taler; see the file COPYING.  If not, see <http://www.gnu.org/licenses/>
+ */
+
+/**
+ *
+ * @author Sebastian Javier Marchano (sebasjm)
+ */
+
+table.table {
+  thead {
+    th {
+      border-bottom-width: 1px;
+    }
+  }
+
+  td,
+  th {
+    &.checkbox-cell {
+      .b-checkbox.checkbox:not(.button) {
+        margin-right: 0;
+        width: 20px;
+
+        .control-label {
+          display: none;
+          padding: 0;
+        }
+      }
+    }
+  }
+
+  td {
+    .image {
+      margin: 0 auto;
+      width: $table-avatar-size;
+      height: $table-avatar-size;
+    }
+
+    &.is-progress-col {
+      min-width: 5rem;
+      vertical-align: middle;
+    }
+  }
+}
+
+.b-table {
+  .table {
+    border: 0;
+    border-radius: 0;
+  }
+
+  /* This stylizes buefy's pagination */
+  .table-wrapper {
+    margin-bottom: 0;
+  }
+
+  .table-wrapper + .level {
+    padding: $notification-padding;
+    padding-left: $card-content-padding;
+    padding-right: $card-content-padding;
+    margin: 0;
+    border-top: $base-color-light;
+    background: $notification-background-color;
+
+    .pagination-link {
+      background: $button-background-color;
+      color: $button-color;
+      border-color: $button-border-color;
+
+      &.is-current {
+        border-color: $button-active-border-color;
+      }
+    }
+
+    .pagination-previous,
+    .pagination-next,
+    .pagination-link {
+      border-color: $button-border-color;
+      color: $base-color;
+
+      &[disabled] {
+        background-color: transparent;
+      }
+    }
+  }
+}
+
+@include mobile {
+  .card {
+    &.has-table {
+      .b-table {
+        .table-wrapper + .level {
+          .level-left + .level-right {
+            margin-top: 0;
+          }
+        }
+      }
+    }
+    &.has-mobile-sort-spaced {
+      .b-table {
+        .field.table-mobile-sort {
+          padding-top: $default-padding * 0.5;
+        }
+      }
+    }
+  }
+  .b-table {
+    .field.table-mobile-sort {
+      padding: 0 $default-padding * 0.5;
+    }
+
+    .table-wrapper.has-mobile-cards {
+      tr {
+        box-shadow: 0 2px 3px rgba(10, 10, 10, 0.1);
+        margin-bottom: 3px !important;
+      }
+      td {
+        &.is-progress-col {
+          span,
+          progress {
+            display: flex;
+            width: 45%;
+            align-items: center;
+            align-self: center;
+          }
+        }
+
+        &.checkbox-cell,
+        &.is-image-cell {
+          border-bottom: 0 !important;
+        }
+
+        &.checkbox-cell,
+        &.is-actions-cell {
+          &:before {
+            display: none;
+          }
+        }
+
+        &.has-no-head-mobile {
+          &:before {
+            display: none;
+          }
+
+          span {
+            display: block;
+            width: 100%;
+          }
+
+          &.is-progress-col {
+            progress {
+              width: 100%;
+            }
+          }
+
+          &.is-image-cell {
+            .image {
+              width: $table-avatar-size-mobile;
+              height: auto;
+              margin: 0 auto $default-padding * 0.25;
+            }
+          }
+        }
+      }
+    }
+  }
+}
diff --git a/packages/auditor-backoffice-ui/src/scss/_theme-default.scss 
b/packages/auditor-backoffice-ui/src/scss/_theme-default.scss
new file mode 100644
index 000000000..e74ece0e9
--- /dev/null
+++ b/packages/auditor-backoffice-ui/src/scss/_theme-default.scss
@@ -0,0 +1,136 @@
+/*
+ This file is part of GNU Taler
+ (C) 2021-2023 Taler Systems S.A.
+
+ GNU Taler is free software; you can redistribute it and/or modify it under the
+ terms of the GNU General Public License as published by the Free Software
+ Foundation; either version 3, or (at your option) any later version.
+
+ GNU Taler is distributed in the hope that it will be useful, but WITHOUT ANY
+ WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
+ A PARTICULAR PURPOSE.  See the GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License along with
+ GNU Taler; see the file COPYING.  If not, see <http://www.gnu.org/licenses/>
+ */
+
+/**
+ *
+ * @author Sebastian Javier Marchano (sebasjm)
+ */
+
+/* We'll need some initial vars to use here */
+@import "node_modules/bulma/sass/utilities/initial-variables";
+
+/* Base: Size  */
+$size-base: 1rem;
+$default-padding: $size-base * 1.5;
+
+/* Default font */
+$family-sans-serif: "Nunito", sans-serif;
+
+/* Base color */
+$base-color: #2e323a;
+$base-color-light: rgba(24, 28, 33, 0.06);
+
+/* General overrides */
+$primary: $turquoise;
+$body-background-color: #f8f8f8;
+$link: $blue;
+$link-visited: $purple;
+$light-border: 1px solid $base-color-light;
+$hr-height: 1px;
+
+/* NavBar: specifics */
+$navbar-input-color: $grey-darker;
+$navbar-input-placeholder-color: $grey-lighter;
+$navbar-box-shadow: 0 1px 0 rgba(24, 28, 33, 0.04);
+$navbar-divider-border: 1px solid rgba($grey-lighter, 0.25);
+$navbar-item-h-padding: $default-padding * 0.75;
+$navbar-avatar-size: 1.75rem;
+
+/* Aside: Bulma override */
+$menu-item-radius: 0;
+$menu-list-link-padding: $size-base * 0.5 0;
+$menu-label-color: lighten($base-color, 25%);
+$menu-item-color: lighten($base-color, 30%);
+$menu-item-hover-color: $white;
+$menu-item-hover-background-color: darken($base-color, 3.5%);
+$menu-item-active-color: $white;
+$menu-item-active-background-color: darken($base-color, 2.5%);
+
+/* Aside: specifics */
+$aside-width: $size-base * 14;
+$aside-mobile-width: $size-base * 15;
+$aside-icon-width: $size-base * 3;
+$aside-submenu-font-size: $size-base * 0.95;
+$aside-box-shadow: none;
+$aside-background-color: $base-color;
+$aside-tools-background-color: darken($aside-background-color, 10%);
+$aside-tools-color: $white;
+
+/* Title Bar: specifics */
+$title-bar-color: $grey;
+$title-bar-active-color: $black-ter;
+
+/* Hero Bar: specifics */
+$hero-bar-background: $white;
+
+/* Card: Bulma override */
+$card-shadow: none;
+$card-header-shadow: none;
+
+/* Card: specifics */
+$card-border: 1px solid $base-color-light;
+$card-header-border-bottom-color: $base-color-light;
+
+/* Table: Bulma override */
+$table-cell-border: 1px solid $white-bis;
+
+/* Table: specifics */
+$table-avatar-size: $size-base * 1.5;
+$table-avatar-size-mobile: 25vw;
+
+/* Form */
+$checkbox-border: 1px solid $base-color;
+
+/* Modal card: Bulma override */
+$modal-card-head-background-color: $white-ter;
+$modal-card-title-size: $size-base;
+$modal-card-body-padding: $default-padding 20px;
+$modal-card-head-border-bottom: 1px solid $white-ter;
+$modal-card-foot-border-top: 0;
+
+/* Modal card: specifics */
+$modal-card-width: 80vw;
+$modal-card-width-mobile: 90vw;
+$modal-card-foot-background-color: $white-ter;
+
+/* Notification: Bulma override */
+$notification-padding: $default-padding * 0.75 $default-padding;
+
+/* Footer: Bulma override */
+$footer-background-color: $white;
+$footer-padding: $default-padding * 0.33 $default-padding;
+
+/* Footer: specifics */
+$footer-logo-height: $size-base * 2;
+
+/* Progress: Bulma override */
+$progress-bar-background-color: $grey-lighter;
+
+/* Icon: specifics */
+$icon-update-mark-size: $size-base * 0.5;
+$icon-update-mark-color: $yellow;
+
+$input-disabled-border-color: $grey-lighter;
+$table-row-hover-background-color: hsl(0, 0%, 80%);
+
+.menu-list {
+  div {
+    border-radius: $menu-item-radius;
+    color: $menu-item-color;
+    display: block;
+    padding: $menu-list-link-padding;
+  }
+}
diff --git a/packages/auditor-backoffice-ui/src/scss/_tiles.scss 
b/packages/auditor-backoffice-ui/src/scss/_tiles.scss
new file mode 100644
index 000000000..94dd6c21d
--- /dev/null
+++ b/packages/auditor-backoffice-ui/src/scss/_tiles.scss
@@ -0,0 +1,24 @@
+/*
+ This file is part of GNU Taler
+ (C) 2021-2023 Taler Systems S.A.
+
+ GNU Taler is free software; you can redistribute it and/or modify it under the
+ terms of the GNU General Public License as published by the Free Software
+ Foundation; either version 3, or (at your option) any later version.
+
+ GNU Taler is distributed in the hope that it will be useful, but WITHOUT ANY
+ WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
+ A PARTICULAR PURPOSE.  See the GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License along with
+ GNU Taler; see the file COPYING.  If not, see <http://www.gnu.org/licenses/>
+ */
+
+/**
+ *
+ * @author Sebastian Javier Marchano (sebasjm)
+ */
+
+.is-tiles-wrapper {
+  margin-bottom: $default-padding;
+}
diff --git a/packages/auditor-backoffice-ui/src/scss/_title-bar.scss 
b/packages/auditor-backoffice-ui/src/scss/_title-bar.scss
new file mode 100644
index 000000000..bac3f6b42
--- /dev/null
+++ b/packages/auditor-backoffice-ui/src/scss/_title-bar.scss
@@ -0,0 +1,50 @@
+/*
+ This file is part of GNU Taler
+ (C) 2021-2023 Taler Systems S.A.
+
+ GNU Taler is free software; you can redistribute it and/or modify it under the
+ terms of the GNU General Public License as published by the Free Software
+ Foundation; either version 3, or (at your option) any later version.
+
+ GNU Taler is distributed in the hope that it will be useful, but WITHOUT ANY
+ WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
+ A PARTICULAR PURPOSE.  See the GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License along with
+ GNU Taler; see the file COPYING.  If not, see <http://www.gnu.org/licenses/>
+ */
+
+/**
+ *
+ * @author Sebastian Javier Marchano (sebasjm)
+ */
+
+section.section.is-title-bar {
+  padding: $default-padding;
+  border-bottom: $light-border;
+
+  ul {
+    li {
+      display: inline-block;
+      padding: 0 $default-padding * 0.5 0 0;
+      font-size: $default-padding;
+      color: $title-bar-color;
+
+      &:after {
+        display: inline-block;
+        content: "/";
+        padding-left: $default-padding * 0.5;
+      }
+
+      &:last-child {
+        padding-right: 0;
+        font-weight: 900;
+        color: $title-bar-active-color;
+
+        &:after {
+          display: none;
+        }
+      }
+    }
+  }
+}
diff --git 
a/packages/auditor-backoffice-ui/src/scss/fonts/XRXV3I6Li01BKofINeaE.ttf 
b/packages/auditor-backoffice-ui/src/scss/fonts/XRXV3I6Li01BKofINeaE.ttf
new file mode 100644
index 000000000..7665ee336
Binary files /dev/null and 
b/packages/auditor-backoffice-ui/src/scss/fonts/XRXV3I6Li01BKofINeaE.ttf differ
diff --git a/packages/auditor-backoffice-ui/src/scss/fonts/nunito.css 
b/packages/auditor-backoffice-ui/src/scss/fonts/nunito.css
new file mode 100644
index 000000000..a578506e8
--- /dev/null
+++ b/packages/auditor-backoffice-ui/src/scss/fonts/nunito.css
@@ -0,0 +1,22 @@
+/*
+ This file is part of GNU Taler
+ (C) 2021-2023 Taler Systems S.A.
+
+ GNU Taler is free software; you can redistribute it and/or modify it under the
+ terms of the GNU General Public License as published by the Free Software
+ Foundation; either version 3, or (at your option) any later version.
+
+ GNU Taler is distributed in the hope that it will be useful, but WITHOUT ANY
+ WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
+ A PARTICULAR PURPOSE.  See the GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License along with
+ GNU Taler; see the file COPYING.  If not, see <http://www.gnu.org/licenses/>
+ */
+
+@font-face {
+  font-family: "Nunito";
+  font-style: normal;
+  font-weight: 400;
+  src: url(./XRXV3I6Li01BKofINeaE.ttf) format("truetype");
+}
diff --git 
a/packages/auditor-backoffice-ui/src/scss/icons/fonts/materialdesignicons-webfont-4.9.95.eot
 
b/packages/auditor-backoffice-ui/src/scss/icons/fonts/materialdesignicons-webfont-4.9.95.eot
new file mode 100644
index 000000000..ab6b25ded
Binary files /dev/null and 
b/packages/auditor-backoffice-ui/src/scss/icons/fonts/materialdesignicons-webfont-4.9.95.eot
 differ
diff --git 
a/packages/auditor-backoffice-ui/src/scss/icons/fonts/materialdesignicons-webfont-4.9.95.ttf
 
b/packages/auditor-backoffice-ui/src/scss/icons/fonts/materialdesignicons-webfont-4.9.95.ttf
new file mode 100644
index 000000000..824be10fa
Binary files /dev/null and 
b/packages/auditor-backoffice-ui/src/scss/icons/fonts/materialdesignicons-webfont-4.9.95.ttf
 differ
diff --git 
a/packages/auditor-backoffice-ui/src/scss/icons/fonts/materialdesignicons-webfont-4.9.95.woff
 
b/packages/auditor-backoffice-ui/src/scss/icons/fonts/materialdesignicons-webfont-4.9.95.woff
new file mode 100644
index 000000000..7e087c1de
Binary files /dev/null and 
b/packages/auditor-backoffice-ui/src/scss/icons/fonts/materialdesignicons-webfont-4.9.95.woff
 differ
diff --git 
a/packages/auditor-backoffice-ui/src/scss/icons/fonts/materialdesignicons-webfont-4.9.95.woff2
 
b/packages/auditor-backoffice-ui/src/scss/icons/fonts/materialdesignicons-webfont-4.9.95.woff2
new file mode 100644
index 000000000..b5caa4ddc
Binary files /dev/null and 
b/packages/auditor-backoffice-ui/src/scss/icons/fonts/materialdesignicons-webfont-4.9.95.woff2
 differ
diff --git 
a/packages/auditor-backoffice-ui/src/scss/icons/materialdesignicons-4.9.95.min.css
 
b/packages/auditor-backoffice-ui/src/scss/icons/materialdesignicons-4.9.95.min.css
new file mode 100644
index 000000000..2b8a2b244
--- /dev/null
+++ 
b/packages/auditor-backoffice-ui/src/scss/icons/materialdesignicons-4.9.95.min.css
@@ -0,0 +1,15109 @@
+@font-face {
+  font-family: "Material Design Icons";
+  src: url("./fonts/materialdesignicons-webfont-4.9.95.eot");
+  src: url("./fonts/materialdesignicons-webfont-4.9.95.woff2") format("woff2"),
+    url("./fonts/materialdesignicons-webfont-4.9.95.woff") format("woff"),
+    url("./fonts/materialdesignicons-webfont-4.9.95.ttf") format("truetype");
+  font-weight: normal;
+  font-style: normal;
+}
+.mdi:before,
+.mdi-set {
+  display: inline-block;
+  font: normal normal normal 24px/1 "Material Design Icons";
+  font-size: inherit;
+  text-rendering: auto;
+  line-height: inherit;
+  -webkit-font-smoothing: antialiased;
+  -moz-osx-font-smoothing: grayscale;
+}
+.mdi-ab-testing::before {
+  content: "\F001C";
+}
+.mdi-abjad-arabic::before {
+  content: "\F0353";
+}
+.mdi-abjad-hebrew::before {
+  content: "\F0354";
+}
+.mdi-abugida-devanagari::before {
+  content: "\F0355";
+}
+.mdi-abugida-thai::before {
+  content: "\F0356";
+}
+.mdi-access-point::before {
+  content: "\F002";
+}
+.mdi-access-point-network::before {
+  content: "\F003";
+}
+.mdi-access-point-network-off::before {
+  content: "\FBBD";
+}
+.mdi-account::before {
+  content: "\F004";
+}
+.mdi-account-alert::before {
+  content: "\F005";
+}
+.mdi-account-alert-outline::before {
+  content: "\FB2C";
+}
+.mdi-account-arrow-left::before {
+  content: "\FB2D";
+}
+.mdi-account-arrow-left-outline::before {
+  content: "\FB2E";
+}
+.mdi-account-arrow-right::before {
+  content: "\FB2F";
+}
+.mdi-account-arrow-right-outline::before {
+  content: "\FB30";
+}
+.mdi-account-badge::before {
+  content: "\FD83";
+}
+.mdi-account-badge-alert::before {
+  content: "\FD84";
+}
+.mdi-account-badge-alert-outline::before {
+  content: "\FD85";
+}
+.mdi-account-badge-horizontal::before {
+  content: "\FDF0";
+}
+.mdi-account-badge-horizontal-outline::before {
+  content: "\FDF1";
+}
+.mdi-account-badge-outline::before {
+  content: "\FD86";
+}
+.mdi-account-box::before {
+  content: "\F006";
+}
+.mdi-account-box-multiple::before {
+  content: "\F933";
+}
+.mdi-account-box-multiple-outline::before {
+  content: "\F002C";
+}
+.mdi-account-box-outline::before {
+  content: "\F007";
+}
+.mdi-account-cancel::before {
+  content: "\F030A";
+}
+.mdi-account-cancel-outline::before {
+  content: "\F030B";
+}
+.mdi-account-card-details::before {
+  content: "\F5D2";
+}
+.mdi-account-card-details-outline::before {
+  content: "\FD87";
+}
+.mdi-account-cash::before {
+  content: "\F00C2";
+}
+.mdi-account-cash-outline::before {
+  content: "\F00C3";
+}
+.mdi-account-check::before {
+  content: "\F008";
+}
+.mdi-account-check-outline::before {
+  content: "\FBBE";
+}
+.mdi-account-child::before {
+  content: "\FA88";
+}
+.mdi-account-child-circle::before {
+  content: "\FA89";
+}
+.mdi-account-child-outline::before {
+  content: "\F00F3";
+}
+.mdi-account-circle::before {
+  content: "\F009";
+}
+.mdi-account-circle-outline::before {
+  content: "\FB31";
+}
+.mdi-account-clock::before {
+  content: "\FB32";
+}
+.mdi-account-clock-outline::before {
+  content: "\FB33";
+}
+.mdi-account-cog::before {
+  content: "\F039B";
+}
+.mdi-account-cog-outline::before {
+  content: "\F039C";
+}
+.mdi-account-convert::before {
+  content: "\F00A";
+}
+.mdi-account-convert-outline::before {
+  content: "\F032C";
+}
+.mdi-account-details::before {
+  content: "\F631";
+}
+.mdi-account-details-outline::before {
+  content: "\F039D";
+}
+.mdi-account-edit::before {
+  content: "\F6BB";
+}
+.mdi-account-edit-outline::before {
+  content: "\F001D";
+}
+.mdi-account-group::before {
+  content: "\F848";
+}
+.mdi-account-group-outline::before {
+  content: "\FB34";
+}
+.mdi-account-heart::before {
+  content: "\F898";
+}
+.mdi-account-heart-outline::before {
+  content: "\FBBF";
+}
+.mdi-account-key::before {
+  content: "\F00B";
+}
+.mdi-account-key-outline::before {
+  content: "\FBC0";
+}
+.mdi-account-lock::before {
+  content: "\F0189";
+}
+.mdi-account-lock-outline::before {
+  content: "\F018A";
+}
+.mdi-account-minus::before {
+  content: "\F00D";
+}
+.mdi-account-minus-outline::before {
+  content: "\FAEB";
+}
+.mdi-account-multiple::before {
+  content: "\F00E";
+}
+.mdi-account-multiple-check::before {
+  content: "\F8C4";
+}
+.mdi-account-multiple-check-outline::before {
+  content: "\F0229";
+}
+.mdi-account-multiple-minus::before {
+  content: "\F5D3";
+}
+.mdi-account-multiple-minus-outline::before {
+  content: "\FBC1";
+}
+.mdi-account-multiple-outline::before {
+  content: "\F00F";
+}
+.mdi-account-multiple-plus::before {
+  content: "\F010";
+}
+.mdi-account-multiple-plus-outline::before {
+  content: "\F7FF";
+}
+.mdi-account-multiple-remove::before {
+  content: "\F0235";
+}
+.mdi-account-multiple-remove-outline::before {
+  content: "\F0236";
+}
+.mdi-account-network::before {
+  content: "\F011";
+}
+.mdi-account-network-outline::before {
+  content: "\FBC2";
+}
+.mdi-account-off::before {
+  content: "\F012";
+}
+.mdi-account-off-outline::before {
+  content: "\FBC3";
+}
+.mdi-account-outline::before {
+  content: "\F013";
+}
+.mdi-account-plus::before {
+  content: "\F014";
+}
+.mdi-account-plus-outline::before {
+  content: "\F800";
+}
+.mdi-account-question::before {
+  content: "\FB35";
+}
+.mdi-account-question-outline::before {
+  content: "\FB36";
+}
+.mdi-account-remove::before {
+  content: "\F015";
+}
+.mdi-account-remove-outline::before {
+  content: "\FAEC";
+}
+.mdi-account-search::before {
+  content: "\F016";
+}
+.mdi-account-search-outline::before {
+  content: "\F934";
+}
+.mdi-account-settings::before {
+  content: "\F630";
+}
+.mdi-account-settings-outline::before {
+  content: "\F00F4";
+}
+.mdi-account-star::before {
+  content: "\F017";
+}
+.mdi-account-star-outline::before {
+  content: "\FBC4";
+}
+.mdi-account-supervisor::before {
+  content: "\FA8A";
+}
+.mdi-account-supervisor-circle::before {
+  content: "\FA8B";
+}
+.mdi-account-supervisor-outline::before {
+  content: "\F0158";
+}
+.mdi-account-switch::before {
+  content: "\F019";
+}
+.mdi-account-tie::before {
+  content: "\FCBF";
+}
+.mdi-account-tie-outline::before {
+  content: "\F00F5";
+}
+.mdi-account-tie-voice::before {
+  content: "\F0333";
+}
+.mdi-account-tie-voice-off::before {
+  content: "\F0335";
+}
+.mdi-account-tie-voice-off-outline::before {
+  content: "\F0336";
+}
+.mdi-account-tie-voice-outline::before {
+  content: "\F0334";
+}
+.mdi-accusoft::before {
+  content: "\F849";
+}
+.mdi-adjust::before {
+  content: "\F01A";
+}
+.mdi-adobe::before {
+  content: "\F935";
+}
+.mdi-adobe-acrobat::before {
+  content: "\FFBD";
+}
+.mdi-air-conditioner::before {
+  content: "\F01B";
+}
+.mdi-air-filter::before {
+  content: "\FD1F";
+}
+.mdi-air-horn::before {
+  content: "\FD88";
+}
+.mdi-air-humidifier::before {
+  content: "\F00C4";
+}
+.mdi-air-purifier::before {
+  content: "\FD20";
+}
+.mdi-airbag::before {
+  content: "\FBC5";
+}
+.mdi-airballoon::before {
+  content: "\F01C";
+}
+.mdi-airballoon-outline::before {
+  content: "\F002D";
+}
+.mdi-airplane::before {
+  content: "\F01D";
+}
+.mdi-airplane-landing::before {
+  content: "\F5D4";
+}
+.mdi-airplane-off::before {
+  content: "\F01E";
+}
+.mdi-airplane-takeoff::before {
+  content: "\F5D5";
+}
+.mdi-airplay::before {
+  content: "\F01F";
+}
+.mdi-airport::before {
+  content: "\F84A";
+}
+.mdi-alarm::before {
+  content: "\F020";
+}
+.mdi-alarm-bell::before {
+  content: "\F78D";
+}
+.mdi-alarm-check::before {
+  content: "\F021";
+}
+.mdi-alarm-light::before {
+  content: "\F78E";
+}
+.mdi-alarm-light-outline::before {
+  content: "\FBC6";
+}
+.mdi-alarm-multiple::before {
+  content: "\F022";
+}
+.mdi-alarm-note::before {
+  content: "\FE8E";
+}
+.mdi-alarm-note-off::before {
+  content: "\FE8F";
+}
+.mdi-alarm-off::before {
+  content: "\F023";
+}
+.mdi-alarm-plus::before {
+  content: "\F024";
+}
+.mdi-alarm-snooze::before {
+  content: "\F68D";
+}
+.mdi-album::before {
+  content: "\F025";
+}
+.mdi-alert::before {
+  content: "\F026";
+}
+.mdi-alert-box::before {
+  content: "\F027";
+}
+.mdi-alert-box-outline::before {
+  content: "\FCC0";
+}
+.mdi-alert-circle::before {
+  content: "\F028";
+}
+.mdi-alert-circle-check::before {
+  content: "\F0218";
+}
+.mdi-alert-circle-check-outline::before {
+  content: "\F0219";
+}
+.mdi-alert-circle-outline::before {
+  content: "\F5D6";
+}
+.mdi-alert-decagram::before {
+  content: "\F6BC";
+}
+.mdi-alert-decagram-outline::before {
+  content: "\FCC1";
+}
+.mdi-alert-octagon::before {
+  content: "\F029";
+}
+.mdi-alert-octagon-outline::before {
+  content: "\FCC2";
+}
+.mdi-alert-octagram::before {
+  content: "\F766";
+}
+.mdi-alert-octagram-outline::before {
+  content: "\FCC3";
+}
+.mdi-alert-outline::before {
+  content: "\F02A";
+}
+.mdi-alert-rhombus::before {
+  content: "\F01F9";
+}
+.mdi-alert-rhombus-outline::before {
+  content: "\F01FA";
+}
+.mdi-alien::before {
+  content: "\F899";
+}
+.mdi-alien-outline::before {
+  content: "\F00F6";
+}
+.mdi-align-horizontal-center::before {
+  content: "\F01EE";
+}
+.mdi-align-horizontal-left::before {
+  content: "\F01ED";
+}
+.mdi-align-horizontal-right::before {
+  content: "\F01EF";
+}
+.mdi-align-vertical-bottom::before {
+  content: "\F01F0";
+}
+.mdi-align-vertical-center::before {
+  content: "\F01F1";
+}
+.mdi-align-vertical-top::before {
+  content: "\F01F2";
+}
+.mdi-all-inclusive::before {
+  content: "\F6BD";
+}
+.mdi-allergy::before {
+  content: "\F0283";
+}
+.mdi-alpha::before {
+  content: "\F02B";
+}
+.mdi-alpha-a::before {
+  content: "\41";
+}
+.mdi-alpha-a-box::before {
+  content: "\FAED";
+}
+.mdi-alpha-a-box-outline::before {
+  content: "\FBC7";
+}
+.mdi-alpha-a-circle::before {
+  content: "\FBC8";
+}
+.mdi-alpha-a-circle-outline::before {
+  content: "\FBC9";
+}
+.mdi-alpha-b::before {
+  content: "\42";
+}
+.mdi-alpha-b-box::before {
+  content: "\FAEE";
+}
+.mdi-alpha-b-box-outline::before {
+  content: "\FBCA";
+}
+.mdi-alpha-b-circle::before {
+  content: "\FBCB";
+}
+.mdi-alpha-b-circle-outline::before {
+  content: "\FBCC";
+}
+.mdi-alpha-c::before {
+  content: "\43";
+}
+.mdi-alpha-c-box::before {
+  content: "\FAEF";
+}
+.mdi-alpha-c-box-outline::before {
+  content: "\FBCD";
+}
+.mdi-alpha-c-circle::before {
+  content: "\FBCE";
+}
+.mdi-alpha-c-circle-outline::before {
+  content: "\FBCF";
+}
+.mdi-alpha-d::before {
+  content: "\44";
+}
+.mdi-alpha-d-box::before {
+  content: "\FAF0";
+}
+.mdi-alpha-d-box-outline::before {
+  content: "\FBD0";
+}
+.mdi-alpha-d-circle::before {
+  content: "\FBD1";
+}
+.mdi-alpha-d-circle-outline::before {
+  content: "\FBD2";
+}
+.mdi-alpha-e::before {
+  content: "\45";
+}
+.mdi-alpha-e-box::before {
+  content: "\FAF1";
+}
+.mdi-alpha-e-box-outline::before {
+  content: "\FBD3";
+}
+.mdi-alpha-e-circle::before {
+  content: "\FBD4";
+}
+.mdi-alpha-e-circle-outline::before {
+  content: "\FBD5";
+}
+.mdi-alpha-f::before {
+  content: "\46";
+}
+.mdi-alpha-f-box::before {
+  content: "\FAF2";
+}
+.mdi-alpha-f-box-outline::before {
+  content: "\FBD6";
+}
+.mdi-alpha-f-circle::before {
+  content: "\FBD7";
+}
+.mdi-alpha-f-circle-outline::before {
+  content: "\FBD8";
+}
+.mdi-alpha-g::before {
+  content: "\47";
+}
+.mdi-alpha-g-box::before {
+  content: "\FAF3";
+}
+.mdi-alpha-g-box-outline::before {
+  content: "\FBD9";
+}
+.mdi-alpha-g-circle::before {
+  content: "\FBDA";
+}
+.mdi-alpha-g-circle-outline::before {
+  content: "\FBDB";
+}
+.mdi-alpha-h::before {
+  content: "\48";
+}
+.mdi-alpha-h-box::before {
+  content: "\FAF4";
+}
+.mdi-alpha-h-box-outline::before {
+  content: "\FBDC";
+}
+.mdi-alpha-h-circle::before {
+  content: "\FBDD";
+}
+.mdi-alpha-h-circle-outline::before {
+  content: "\FBDE";
+}
+.mdi-alpha-i::before {
+  content: "\49";
+}
+.mdi-alpha-i-box::before {
+  content: "\FAF5";
+}
+.mdi-alpha-i-box-outline::before {
+  content: "\FBDF";
+}
+.mdi-alpha-i-circle::before {
+  content: "\FBE0";
+}
+.mdi-alpha-i-circle-outline::before {
+  content: "\FBE1";
+}
+.mdi-alpha-j::before {
+  content: "\4A";
+}
+.mdi-alpha-j-box::before {
+  content: "\FAF6";
+}
+.mdi-alpha-j-box-outline::before {
+  content: "\FBE2";
+}
+.mdi-alpha-j-circle::before {
+  content: "\FBE3";
+}
+.mdi-alpha-j-circle-outline::before {
+  content: "\FBE4";
+}
+.mdi-alpha-k::before {
+  content: "\4B";
+}
+.mdi-alpha-k-box::before {
+  content: "\FAF7";
+}
+.mdi-alpha-k-box-outline::before {
+  content: "\FBE5";
+}
+.mdi-alpha-k-circle::before {
+  content: "\FBE6";
+}
+.mdi-alpha-k-circle-outline::before {
+  content: "\FBE7";
+}
+.mdi-alpha-l::before {
+  content: "\4C";
+}
+.mdi-alpha-l-box::before {
+  content: "\FAF8";
+}
+.mdi-alpha-l-box-outline::before {
+  content: "\FBE8";
+}
+.mdi-alpha-l-circle::before {
+  content: "\FBE9";
+}
+.mdi-alpha-l-circle-outline::before {
+  content: "\FBEA";
+}
+.mdi-alpha-m::before {
+  content: "\4D";
+}
+.mdi-alpha-m-box::before {
+  content: "\FAF9";
+}
+.mdi-alpha-m-box-outline::before {
+  content: "\FBEB";
+}
+.mdi-alpha-m-circle::before {
+  content: "\FBEC";
+}
+.mdi-alpha-m-circle-outline::before {
+  content: "\FBED";
+}
+.mdi-alpha-n::before {
+  content: "\4E";
+}
+.mdi-alpha-n-box::before {
+  content: "\FAFA";
+}
+.mdi-alpha-n-box-outline::before {
+  content: "\FBEE";
+}
+.mdi-alpha-n-circle::before {
+  content: "\FBEF";
+}
+.mdi-alpha-n-circle-outline::before {
+  content: "\FBF0";
+}
+.mdi-alpha-o::before {
+  content: "\4F";
+}
+.mdi-alpha-o-box::before {
+  content: "\FAFB";
+}
+.mdi-alpha-o-box-outline::before {
+  content: "\FBF1";
+}
+.mdi-alpha-o-circle::before {
+  content: "\FBF2";
+}
+.mdi-alpha-o-circle-outline::before {
+  content: "\FBF3";
+}
+.mdi-alpha-p::before {
+  content: "\50";
+}
+.mdi-alpha-p-box::before {
+  content: "\FAFC";
+}
+.mdi-alpha-p-box-outline::before {
+  content: "\FBF4";
+}
+.mdi-alpha-p-circle::before {
+  content: "\FBF5";
+}
+.mdi-alpha-p-circle-outline::before {
+  content: "\FBF6";
+}
+.mdi-alpha-q::before {
+  content: "\51";
+}
+.mdi-alpha-q-box::before {
+  content: "\FAFD";
+}
+.mdi-alpha-q-box-outline::before {
+  content: "\FBF7";
+}
+.mdi-alpha-q-circle::before {
+  content: "\FBF8";
+}
+.mdi-alpha-q-circle-outline::before {
+  content: "\FBF9";
+}
+.mdi-alpha-r::before {
+  content: "\52";
+}
+.mdi-alpha-r-box::before {
+  content: "\FAFE";
+}
+.mdi-alpha-r-box-outline::before {
+  content: "\FBFA";
+}
+.mdi-alpha-r-circle::before {
+  content: "\FBFB";
+}
+.mdi-alpha-r-circle-outline::before {
+  content: "\FBFC";
+}
+.mdi-alpha-s::before {
+  content: "\53";
+}
+.mdi-alpha-s-box::before {
+  content: "\FAFF";
+}
+.mdi-alpha-s-box-outline::before {
+  content: "\FBFD";
+}
+.mdi-alpha-s-circle::before {
+  content: "\FBFE";
+}
+.mdi-alpha-s-circle-outline::before {
+  content: "\FBFF";
+}
+.mdi-alpha-t::before {
+  content: "\54";
+}
+.mdi-alpha-t-box::before {
+  content: "\FB00";
+}
+.mdi-alpha-t-box-outline::before {
+  content: "\FC00";
+}
+.mdi-alpha-t-circle::before {
+  content: "\FC01";
+}
+.mdi-alpha-t-circle-outline::before {
+  content: "\FC02";
+}
+.mdi-alpha-u::before {
+  content: "\55";
+}
+.mdi-alpha-u-box::before {
+  content: "\FB01";
+}
+.mdi-alpha-u-box-outline::before {
+  content: "\FC03";
+}
+.mdi-alpha-u-circle::before {
+  content: "\FC04";
+}
+.mdi-alpha-u-circle-outline::before {
+  content: "\FC05";
+}
+.mdi-alpha-v::before {
+  content: "\56";
+}
+.mdi-alpha-v-box::before {
+  content: "\FB02";
+}
+.mdi-alpha-v-box-outline::before {
+  content: "\FC06";
+}
+.mdi-alpha-v-circle::before {
+  content: "\FC07";
+}
+.mdi-alpha-v-circle-outline::before {
+  content: "\FC08";
+}
+.mdi-alpha-w::before {
+  content: "\57";
+}
+.mdi-alpha-w-box::before {
+  content: "\FB03";
+}
+.mdi-alpha-w-box-outline::before {
+  content: "\FC09";
+}
+.mdi-alpha-w-circle::before {
+  content: "\FC0A";
+}
+.mdi-alpha-w-circle-outline::before {
+  content: "\FC0B";
+}
+.mdi-alpha-x::before {
+  content: "\58";
+}
+.mdi-alpha-x-box::before {
+  content: "\FB04";
+}
+.mdi-alpha-x-box-outline::before {
+  content: "\FC0C";
+}
+.mdi-alpha-x-circle::before {
+  content: "\FC0D";
+}
+.mdi-alpha-x-circle-outline::before {
+  content: "\FC0E";
+}
+.mdi-alpha-y::before {
+  content: "\59";
+}
+.mdi-alpha-y-box::before {
+  content: "\FB05";
+}
+.mdi-alpha-y-box-outline::before {
+  content: "\FC0F";
+}
+.mdi-alpha-y-circle::before {
+  content: "\FC10";
+}
+.mdi-alpha-y-circle-outline::before {
+  content: "\FC11";
+}
+.mdi-alpha-z::before {
+  content: "\5A";
+}
+.mdi-alpha-z-box::before {
+  content: "\FB06";
+}
+.mdi-alpha-z-box-outline::before {
+  content: "\FC12";
+}
+.mdi-alpha-z-circle::before {
+  content: "\FC13";
+}
+.mdi-alpha-z-circle-outline::before {
+  content: "\FC14";
+}
+.mdi-alphabet-aurebesh::before {
+  content: "\F0357";
+}
+.mdi-alphabet-cyrillic::before {
+  content: "\F0358";
+}
+.mdi-alphabet-greek::before {
+  content: "\F0359";
+}
+.mdi-alphabet-latin::before {
+  content: "\F035A";
+}
+.mdi-alphabet-piqad::before {
+  content: "\F035B";
+}
+.mdi-alphabet-tengwar::before {
+  content: "\F0362";
+}
+.mdi-alphabetical::before {
+  content: "\F02C";
+}
+.mdi-alphabetical-off::before {
+  content: "\F002E";
+}
+.mdi-alphabetical-variant::before {
+  content: "\F002F";
+}
+.mdi-alphabetical-variant-off::before {
+  content: "\F0030";
+}
+.mdi-altimeter::before {
+  content: "\F5D7";
+}
+.mdi-amazon::before {
+  content: "\F02D";
+}
+.mdi-amazon-alexa::before {
+  content: "\F8C5";
+}
+.mdi-amazon-drive::before {
+  content: "\F02E";
+}
+.mdi-ambulance::before {
+  content: "\F02F";
+}
+.mdi-ammunition::before {
+  content: "\FCC4";
+}
+.mdi-ampersand::before {
+  content: "\FA8C";
+}
+.mdi-amplifier::before {
+  content: "\F030";
+}
+.mdi-amplifier-off::before {
+  content: "\F01E0";
+}
+.mdi-anchor::before {
+  content: "\F031";
+}
+.mdi-android::before {
+  content: "\F032";
+}
+.mdi-android-auto::before {
+  content: "\FA8D";
+}
+.mdi-android-debug-bridge::before {
+  content: "\F033";
+}
+.mdi-android-head::before {
+  content: "\F78F";
+}
+.mdi-android-messages::before {
+  content: "\FD21";
+}
+.mdi-android-studio::before {
+  content: "\F034";
+}
+.mdi-angle-acute::before {
+  content: "\F936";
+}
+.mdi-angle-obtuse::before {
+  content: "\F937";
+}
+.mdi-angle-right::before {
+  content: "\F938";
+}
+.mdi-angular::before {
+  content: "\F6B1";
+}
+.mdi-angularjs::before {
+  content: "\F6BE";
+}
+.mdi-animation::before {
+  content: "\F5D8";
+}
+.mdi-animation-outline::before {
+  content: "\FA8E";
+}
+.mdi-animation-play::before {
+  content: "\F939";
+}
+.mdi-animation-play-outline::before {
+  content: "\FA8F";
+}
+.mdi-ansible::before {
+  content: "\F00C5";
+}
+.mdi-antenna::before {
+  content: "\F0144";
+}
+.mdi-anvil::before {
+  content: "\F89A";
+}
+.mdi-apache-kafka::before {
+  content: "\F0031";
+}
+.mdi-api::before {
+  content: "\F00C6";
+}
+.mdi-api-off::before {
+  content: "\F0282";
+}
+.mdi-apple::before {
+  content: "\F035";
+}
+.mdi-apple-finder::before {
+  content: "\F036";
+}
+.mdi-apple-icloud::before {
+  content: "\F038";
+}
+.mdi-apple-ios::before {
+  content: "\F037";
+}
+.mdi-apple-keyboard-caps::before {
+  content: "\F632";
+}
+.mdi-apple-keyboard-command::before {
+  content: "\F633";
+}
+.mdi-apple-keyboard-control::before {
+  content: "\F634";
+}
+.mdi-apple-keyboard-option::before {
+  content: "\F635";
+}
+.mdi-apple-keyboard-shift::before {
+  content: "\F636";
+}
+.mdi-apple-safari::before {
+  content: "\F039";
+}
+.mdi-application::before {
+  content: "\F614";
+}
+.mdi-application-export::before {
+  content: "\FD89";
+}
+.mdi-application-import::before {
+  content: "\FD8A";
+}
+.mdi-approximately-equal::before {
+  content: "\FFBE";
+}
+.mdi-approximately-equal-box::before {
+  content: "\FFBF";
+}
+.mdi-apps::before {
+  content: "\F03B";
+}
+.mdi-apps-box::before {
+  content: "\FD22";
+}
+.mdi-arch::before {
+  content: "\F8C6";
+}
+.mdi-archive::before {
+  content: "\F03C";
+}
+.mdi-archive-arrow-down::before {
+  content: "\F0284";
+}
+.mdi-archive-arrow-down-outline::before {
+  content: "\F0285";
+}
+.mdi-archive-arrow-up::before {
+  content: "\F0286";
+}
+.mdi-archive-arrow-up-outline::before {
+  content: "\F0287";
+}
+.mdi-archive-outline::before {
+  content: "\F0239";
+}
+.mdi-arm-flex::before {
+  content: "\F008F";
+}
+.mdi-arm-flex-outline::before {
+  content: "\F0090";
+}
+.mdi-arrange-bring-forward::before {
+  content: "\F03D";
+}
+.mdi-arrange-bring-to-front::before {
+  content: "\F03E";
+}
+.mdi-arrange-send-backward::before {
+  content: "\F03F";
+}
+.mdi-arrange-send-to-back::before {
+  content: "\F040";
+}
+.mdi-arrow-all::before {
+  content: "\F041";
+}
+.mdi-arrow-bottom-left::before {
+  content: "\F042";
+}
+.mdi-arrow-bottom-left-bold-outline::before {
+  content: "\F9B6";
+}
+.mdi-arrow-bottom-left-thick::before {
+  content: "\F9B7";
+}
+.mdi-arrow-bottom-right::before {
+  content: "\F043";
+}
+.mdi-arrow-bottom-right-bold-outline::before {
+  content: "\F9B8";
+}
+.mdi-arrow-bottom-right-thick::before {
+  content: "\F9B9";
+}
+.mdi-arrow-collapse::before {
+  content: "\F615";
+}
+.mdi-arrow-collapse-all::before {
+  content: "\F044";
+}
+.mdi-arrow-collapse-down::before {
+  content: "\F791";
+}
+.mdi-arrow-collapse-horizontal::before {
+  content: "\F84B";
+}
+.mdi-arrow-collapse-left::before {
+  content: "\F792";
+}
+.mdi-arrow-collapse-right::before {
+  content: "\F793";
+}
+.mdi-arrow-collapse-up::before {
+  content: "\F794";
+}
+.mdi-arrow-collapse-vertical::before {
+  content: "\F84C";
+}
+.mdi-arrow-decision::before {
+  content: "\F9BA";
+}
+.mdi-arrow-decision-auto::before {
+  content: "\F9BB";
+}
+.mdi-arrow-decision-auto-outline::before {
+  content: "\F9BC";
+}
+.mdi-arrow-decision-outline::before {
+  content: "\F9BD";
+}
+.mdi-arrow-down::before {
+  content: "\F045";
+}
+.mdi-arrow-down-bold::before {
+  content: "\F72D";
+}
+.mdi-arrow-down-bold-box::before {
+  content: "\F72E";
+}
+.mdi-arrow-down-bold-box-outline::before {
+  content: "\F72F";
+}
+.mdi-arrow-down-bold-circle::before {
+  content: "\F047";
+}
+.mdi-arrow-down-bold-circle-outline::before {
+  content: "\F048";
+}
+.mdi-arrow-down-bold-hexagon-outline::before {
+  content: "\F049";
+}
+.mdi-arrow-down-bold-outline::before {
+  content: "\F9BE";
+}
+.mdi-arrow-down-box::before {
+  content: "\F6BF";
+}
+.mdi-arrow-down-circle::before {
+  content: "\FCB7";
+}
+.mdi-arrow-down-circle-outline::before {
+  content: "\FCB8";
+}
+.mdi-arrow-down-drop-circle::before {
+  content: "\F04A";
+}
+.mdi-arrow-down-drop-circle-outline::before {
+  content: "\F04B";
+}
+.mdi-arrow-down-thick::before {
+  content: "\F046";
+}
+.mdi-arrow-expand::before {
+  content: "\F616";
+}
+.mdi-arrow-expand-all::before {
+  content: "\F04C";
+}
+.mdi-arrow-expand-down::before {
+  content: "\F795";
+}
+.mdi-arrow-expand-horizontal::before {
+  content: "\F84D";
+}
+.mdi-arrow-expand-left::before {
+  content: "\F796";
+}
+.mdi-arrow-expand-right::before {
+  content: "\F797";
+}
+.mdi-arrow-expand-up::before {
+  content: "\F798";
+}
+.mdi-arrow-expand-vertical::before {
+  content: "\F84E";
+}
+.mdi-arrow-horizontal-lock::before {
+  content: "\F0186";
+}
+.mdi-arrow-left::before {
+  content: "\F04D";
+}
+.mdi-arrow-left-bold::before {
+  content: "\F730";
+}
+.mdi-arrow-left-bold-box::before {
+  content: "\F731";
+}
+.mdi-arrow-left-bold-box-outline::before {
+  content: "\F732";
+}
+.mdi-arrow-left-bold-circle::before {
+  content: "\F04F";
+}
+.mdi-arrow-left-bold-circle-outline::before {
+  content: "\F050";
+}
+.mdi-arrow-left-bold-hexagon-outline::before {
+  content: "\F051";
+}
+.mdi-arrow-left-bold-outline::before {
+  content: "\F9BF";
+}
+.mdi-arrow-left-box::before {
+  content: "\F6C0";
+}
+.mdi-arrow-left-circle::before {
+  content: "\FCB9";
+}
+.mdi-arrow-left-circle-outline::before {
+  content: "\FCBA";
+}
+.mdi-arrow-left-drop-circle::before {
+  content: "\F052";
+}
+.mdi-arrow-left-drop-circle-outline::before {
+  content: "\F053";
+}
+.mdi-arrow-left-right::before {
+  content: "\FE90";
+}
+.mdi-arrow-left-right-bold::before {
+  content: "\FE91";
+}
+.mdi-arrow-left-right-bold-outline::before {
+  content: "\F9C0";
+}
+.mdi-arrow-left-thick::before {
+  content: "\F04E";
+}
+.mdi-arrow-right::before {
+  content: "\F054";
+}
+.mdi-arrow-right-bold::before {
+  content: "\F733";
+}
+.mdi-arrow-right-bold-box::before {
+  content: "\F734";
+}
+.mdi-arrow-right-bold-box-outline::before {
+  content: "\F735";
+}
+.mdi-arrow-right-bold-circle::before {
+  content: "\F056";
+}
+.mdi-arrow-right-bold-circle-outline::before {
+  content: "\F057";
+}
+.mdi-arrow-right-bold-hexagon-outline::before {
+  content: "\F058";
+}
+.mdi-arrow-right-bold-outline::before {
+  content: "\F9C1";
+}
+.mdi-arrow-right-box::before {
+  content: "\F6C1";
+}
+.mdi-arrow-right-circle::before {
+  content: "\FCBB";
+}
+.mdi-arrow-right-circle-outline::before {
+  content: "\FCBC";
+}
+.mdi-arrow-right-drop-circle::before {
+  content: "\F059";
+}
+.mdi-arrow-right-drop-circle-outline::before {
+  content: "\F05A";
+}
+.mdi-arrow-right-thick::before {
+  content: "\F055";
+}
+.mdi-arrow-split-horizontal::before {
+  content: "\F93A";
+}
+.mdi-arrow-split-vertical::before {
+  content: "\F93B";
+}
+.mdi-arrow-top-left::before {
+  content: "\F05B";
+}
+.mdi-arrow-top-left-bold-outline::before {
+  content: "\F9C2";
+}
+.mdi-arrow-top-left-bottom-right::before {
+  content: "\FE92";
+}
+.mdi-arrow-top-left-bottom-right-bold::before {
+  content: "\FE93";
+}
+.mdi-arrow-top-left-thick::before {
+  content: "\F9C3";
+}
+.mdi-arrow-top-right::before {
+  content: "\F05C";
+}
+.mdi-arrow-top-right-bold-outline::before {
+  content: "\F9C4";
+}
+.mdi-arrow-top-right-bottom-left::before {
+  content: "\FE94";
+}
+.mdi-arrow-top-right-bottom-left-bold::before {
+  content: "\FE95";
+}
+.mdi-arrow-top-right-thick::before {
+  content: "\F9C5";
+}
+.mdi-arrow-up::before {
+  content: "\F05D";
+}
+.mdi-arrow-up-bold::before {
+  content: "\F736";
+}
+.mdi-arrow-up-bold-box::before {
+  content: "\F737";
+}
+.mdi-arrow-up-bold-box-outline::before {
+  content: "\F738";
+}
+.mdi-arrow-up-bold-circle::before {
+  content: "\F05F";
+}
+.mdi-arrow-up-bold-circle-outline::before {
+  content: "\F060";
+}
+.mdi-arrow-up-bold-hexagon-outline::before {
+  content: "\F061";
+}
+.mdi-arrow-up-bold-outline::before {
+  content: "\F9C6";
+}
+.mdi-arrow-up-box::before {
+  content: "\F6C2";
+}
+.mdi-arrow-up-circle::before {
+  content: "\FCBD";
+}
+.mdi-arrow-up-circle-outline::before {
+  content: "\FCBE";
+}
+.mdi-arrow-up-down::before {
+  content: "\FE96";
+}
+.mdi-arrow-up-down-bold::before {
+  content: "\FE97";
+}
+.mdi-arrow-up-down-bold-outline::before {
+  content: "\F9C7";
+}
+.mdi-arrow-up-drop-circle::before {
+  content: "\F062";
+}
+.mdi-arrow-up-drop-circle-outline::before {
+  content: "\F063";
+}
+.mdi-arrow-up-thick::before {
+  content: "\F05E";
+}
+.mdi-arrow-vertical-lock::before {
+  content: "\F0187";
+}
+.mdi-artist::before {
+  content: "\F802";
+}
+.mdi-artist-outline::before {
+  content: "\FCC5";
+}
+.mdi-artstation::before {
+  content: "\FB37";
+}
+.mdi-aspect-ratio::before {
+  content: "\FA23";
+}
+.mdi-assistant::before {
+  content: "\F064";
+}
+.mdi-asterisk::before {
+  content: "\F6C3";
+}
+.mdi-at::before {
+  content: "\F065";
+}
+.mdi-atlassian::before {
+  content: "\F803";
+}
+.mdi-atm::before {
+  content: "\FD23";
+}
+.mdi-atom::before {
+  content: "\F767";
+}
+.mdi-atom-variant::before {
+  content: "\FE98";
+}
+.mdi-attachment::before {
+  content: "\F066";
+}
+.mdi-audio-video::before {
+  content: "\F93C";
+}
+.mdi-audio-video-off::before {
+  content: "\F01E1";
+}
+.mdi-audiobook::before {
+  content: "\F067";
+}
+.mdi-augmented-reality::before {
+  content: "\F84F";
+}
+.mdi-auto-download::before {
+  content: "\F03A9";
+}
+.mdi-auto-fix::before {
+  content: "\F068";
+}
+.mdi-auto-upload::before {
+  content: "\F069";
+}
+.mdi-autorenew::before {
+  content: "\F06A";
+}
+.mdi-av-timer::before {
+  content: "\F06B";
+}
+.mdi-aws::before {
+  content: "\FDF2";
+}
+.mdi-axe::before {
+  content: "\F8C7";
+}
+.mdi-axis::before {
+  content: "\FD24";
+}
+.mdi-axis-arrow::before {
+  content: "\FD25";
+}
+.mdi-axis-arrow-lock::before {
+  content: "\FD26";
+}
+.mdi-axis-lock::before {
+  content: "\FD27";
+}
+.mdi-axis-x-arrow::before {
+  content: "\FD28";
+}
+.mdi-axis-x-arrow-lock::before {
+  content: "\FD29";
+}
+.mdi-axis-x-rotate-clockwise::before {
+  content: "\FD2A";
+}
+.mdi-axis-x-rotate-counterclockwise::before {
+  content: "\FD2B";
+}
+.mdi-axis-x-y-arrow-lock::before {
+  content: "\FD2C";
+}
+.mdi-axis-y-arrow::before {
+  content: "\FD2D";
+}
+.mdi-axis-y-arrow-lock::before {
+  content: "\FD2E";
+}
+.mdi-axis-y-rotate-clockwise::before {
+  content: "\FD2F";
+}
+.mdi-axis-y-rotate-counterclockwise::before {
+  content: "\FD30";
+}
+.mdi-axis-z-arrow::before {
+  content: "\FD31";
+}
+.mdi-axis-z-arrow-lock::before {
+  content: "\FD32";
+}
+.mdi-axis-z-rotate-clockwise::before {
+  content: "\FD33";
+}
+.mdi-axis-z-rotate-counterclockwise::before {
+  content: "\FD34";
+}
+.mdi-azure::before {
+  content: "\F804";
+}
+.mdi-azure-devops::before {
+  content: "\F0091";
+}
+.mdi-babel::before {
+  content: "\FA24";
+}
+.mdi-baby::before {
+  content: "\F06C";
+}
+.mdi-baby-bottle::before {
+  content: "\FF56";
+}
+.mdi-baby-bottle-outline::before {
+  content: "\FF57";
+}
+.mdi-baby-carriage::before {
+  content: "\F68E";
+}
+.mdi-baby-carriage-off::before {
+  content: "\FFC0";
+}
+.mdi-baby-face::before {
+  content: "\FE99";
+}
+.mdi-baby-face-outline::before {
+  content: "\FE9A";
+}
+.mdi-backburger::before {
+  content: "\F06D";
+}
+.mdi-backspace::before {
+  content: "\F06E";
+}
+.mdi-backspace-outline::before {
+  content: "\FB38";
+}
+.mdi-backspace-reverse::before {
+  content: "\FE9B";
+}
+.mdi-backspace-reverse-outline::before {
+  content: "\FE9C";
+}
+.mdi-backup-restore::before {
+  content: "\F06F";
+}
+.mdi-bacteria::before {
+  content: "\FEF2";
+}
+.mdi-bacteria-outline::before {
+  content: "\FEF3";
+}
+.mdi-badminton::before {
+  content: "\F850";
+}
+.mdi-bag-carry-on::before {
+  content: "\FF58";
+}
+.mdi-bag-carry-on-check::before {
+  content: "\FD41";
+}
+.mdi-bag-carry-on-off::before {
+  content: "\FF59";
+}
+.mdi-bag-checked::before {
+  content: "\FF5A";
+}
+.mdi-bag-personal::before {
+  content: "\FDF3";
+}
+.mdi-bag-personal-off::before {
+  content: "\FDF4";
+}
+.mdi-bag-personal-off-outline::before {
+  content: "\FDF5";
+}
+.mdi-bag-personal-outline::before {
+  content: "\FDF6";
+}
+.mdi-baguette::before {
+  content: "\FF5B";
+}
+.mdi-balloon::before {
+  content: "\FA25";
+}
+.mdi-ballot::before {
+  content: "\F9C8";
+}
+.mdi-ballot-outline::before {
+  content: "\F9C9";
+}
+.mdi-ballot-recount::before {
+  content: "\FC15";
+}
+.mdi-ballot-recount-outline::before {
+  content: "\FC16";
+}
+.mdi-bandage::before {
+  content: "\FD8B";
+}
+.mdi-bandcamp::before {
+  content: "\F674";
+}
+.mdi-bank::before {
+  content: "\F070";
+}
+.mdi-bank-minus::before {
+  content: "\FD8C";
+}
+.mdi-bank-outline::before {
+  content: "\FE9D";
+}
+.mdi-bank-plus::before {
+  content: "\FD8D";
+}
+.mdi-bank-remove::before {
+  content: "\FD8E";
+}
+.mdi-bank-transfer::before {
+  content: "\FA26";
+}
+.mdi-bank-transfer-in::before {
+  content: "\FA27";
+}
+.mdi-bank-transfer-out::before {
+  content: "\FA28";
+}
+.mdi-barcode::before {
+  content: "\F071";
+}
+.mdi-barcode-off::before {
+  content: "\F0261";
+}
+.mdi-barcode-scan::before {
+  content: "\F072";
+}
+.mdi-barley::before {
+  content: "\F073";
+}
+.mdi-barley-off::before {
+  content: "\FB39";
+}
+.mdi-barn::before {
+  content: "\FB3A";
+}
+.mdi-barrel::before {
+  content: "\F074";
+}
+.mdi-baseball::before {
+  content: "\F851";
+}
+.mdi-baseball-bat::before {
+  content: "\F852";
+}
+.mdi-basecamp::before {
+  content: "\F075";
+}
+.mdi-bash::before {
+  content: "\F01AE";
+}
+.mdi-basket::before {
+  content: "\F076";
+}
+.mdi-basket-fill::before {
+  content: "\F077";
+}
+.mdi-basket-outline::before {
+  content: "\F01AC";
+}
+.mdi-basket-unfill::before {
+  content: "\F078";
+}
+.mdi-basketball::before {
+  content: "\F805";
+}
+.mdi-basketball-hoop::before {
+  content: "\FC17";
+}
+.mdi-basketball-hoop-outline::before {
+  content: "\FC18";
+}
+.mdi-bat::before {
+  content: "\FB3B";
+}
+.mdi-battery::before {
+  content: "\F079";
+}
+.mdi-battery-10::before {
+  content: "\F07A";
+}
+.mdi-battery-10-bluetooth::before {
+  content: "\F93D";
+}
+.mdi-battery-20::before {
+  content: "\F07B";
+}
+.mdi-battery-20-bluetooth::before {
+  content: "\F93E";
+}
+.mdi-battery-30::before {
+  content: "\F07C";
+}
+.mdi-battery-30-bluetooth::before {
+  content: "\F93F";
+}
+.mdi-battery-40::before {
+  content: "\F07D";
+}
+.mdi-battery-40-bluetooth::before {
+  content: "\F940";
+}
+.mdi-battery-50::before {
+  content: "\F07E";
+}
+.mdi-battery-50-bluetooth::before {
+  content: "\F941";
+}
+.mdi-battery-60::before {
+  content: "\F07F";
+}
+.mdi-battery-60-bluetooth::before {
+  content: "\F942";
+}
+.mdi-battery-70::before {
+  content: "\F080";
+}
+.mdi-battery-70-bluetooth::before {
+  content: "\F943";
+}
+.mdi-battery-80::before {
+  content: "\F081";
+}
+.mdi-battery-80-bluetooth::before {
+  content: "\F944";
+}
+.mdi-battery-90::before {
+  content: "\F082";
+}
+.mdi-battery-90-bluetooth::before {
+  content: "\F945";
+}
+.mdi-battery-alert::before {
+  content: "\F083";
+}
+.mdi-battery-alert-bluetooth::before {
+  content: "\F946";
+}
+.mdi-battery-alert-variant::before {
+  content: "\F00F7";
+}
+.mdi-battery-alert-variant-outline::before {
+  content: "\F00F8";
+}
+.mdi-battery-bluetooth::before {
+  content: "\F947";
+}
+.mdi-battery-bluetooth-variant::before {
+  content: "\F948";
+}
+.mdi-battery-charging::before {
+  content: "\F084";
+}
+.mdi-battery-charging-10::before {
+  content: "\F89B";
+}
+.mdi-battery-charging-100::before {
+  content: "\F085";
+}
+.mdi-battery-charging-20::before {
+  content: "\F086";
+}
+.mdi-battery-charging-30::before {
+  content: "\F087";
+}
+.mdi-battery-charging-40::before {
+  content: "\F088";
+}
+.mdi-battery-charging-50::before {
+  content: "\F89C";
+}
+.mdi-battery-charging-60::before {
+  content: "\F089";
+}
+.mdi-battery-charging-70::before {
+  content: "\F89D";
+}
+.mdi-battery-charging-80::before {
+  content: "\F08A";
+}
+.mdi-battery-charging-90::before {
+  content: "\F08B";
+}
+.mdi-battery-charging-high::before {
+  content: "\F02D1";
+}
+.mdi-battery-charging-low::before {
+  content: "\F02CF";
+}
+.mdi-battery-charging-medium::before {
+  content: "\F02D0";
+}
+.mdi-battery-charging-outline::before {
+  content: "\F89E";
+}
+.mdi-battery-charging-wireless::before {
+  content: "\F806";
+}
+.mdi-battery-charging-wireless-10::before {
+  content: "\F807";
+}
+.mdi-battery-charging-wireless-20::before {
+  content: "\F808";
+}
+.mdi-battery-charging-wireless-30::before {
+  content: "\F809";
+}
+.mdi-battery-charging-wireless-40::before {
+  content: "\F80A";
+}
+.mdi-battery-charging-wireless-50::before {
+  content: "\F80B";
+}
+.mdi-battery-charging-wireless-60::before {
+  content: "\F80C";
+}
+.mdi-battery-charging-wireless-70::before {
+  content: "\F80D";
+}
+.mdi-battery-charging-wireless-80::before {
+  content: "\F80E";
+}
+.mdi-battery-charging-wireless-90::before {
+  content: "\F80F";
+}
+.mdi-battery-charging-wireless-alert::before {
+  content: "\F810";
+}
+.mdi-battery-charging-wireless-outline::before {
+  content: "\F811";
+}
+.mdi-battery-heart::before {
+  content: "\F023A";
+}
+.mdi-battery-heart-outline::before {
+  content: "\F023B";
+}
+.mdi-battery-heart-variant::before {
+  content: "\F023C";
+}
+.mdi-battery-high::before {
+  content: "\F02CE";
+}
+.mdi-battery-low::before {
+  content: "\F02CC";
+}
+.mdi-battery-medium::before {
+  content: "\F02CD";
+}
+.mdi-battery-minus::before {
+  content: "\F08C";
+}
+.mdi-battery-negative::before {
+  content: "\F08D";
+}
+.mdi-battery-off::before {
+  content: "\F0288";
+}
+.mdi-battery-off-outline::before {
+  content: "\F0289";
+}
+.mdi-battery-outline::before {
+  content: "\F08E";
+}
+.mdi-battery-plus::before {
+  content: "\F08F";
+}
+.mdi-battery-positive::before {
+  content: "\F090";
+}
+.mdi-battery-unknown::before {
+  content: "\F091";
+}
+.mdi-battery-unknown-bluetooth::before {
+  content: "\F949";
+}
+.mdi-battlenet::before {
+  content: "\FB3C";
+}
+.mdi-beach::before {
+  content: "\F092";
+}
+.mdi-beaker::before {
+  content: "\FCC6";
+}
+.mdi-beaker-alert::before {
+  content: "\F0254";
+}
+.mdi-beaker-alert-outline::before {
+  content: "\F0255";
+}
+.mdi-beaker-check::before {
+  content: "\F0256";
+}
+.mdi-beaker-check-outline::before {
+  content: "\F0257";
+}
+.mdi-beaker-minus::before {
+  content: "\F0258";
+}
+.mdi-beaker-minus-outline::before {
+  content: "\F0259";
+}
+.mdi-beaker-outline::before {
+  content: "\F68F";
+}
+.mdi-beaker-plus::before {
+  content: "\F025A";
+}
+.mdi-beaker-plus-outline::before {
+  content: "\F025B";
+}
+.mdi-beaker-question::before {
+  content: "\F025C";
+}
+.mdi-beaker-question-outline::before {
+  content: "\F025D";
+}
+.mdi-beaker-remove::before {
+  content: "\F025E";
+}
+.mdi-beaker-remove-outline::before {
+  content: "\F025F";
+}
+.mdi-beats::before {
+  content: "\F097";
+}
+.mdi-bed-double::before {
+  content: "\F0092";
+}
+.mdi-bed-double-outline::before {
+  content: "\F0093";
+}
+.mdi-bed-empty::before {
+  content: "\F89F";
+}
+.mdi-bed-king::before {
+  content: "\F0094";
+}
+.mdi-bed-king-outline::before {
+  content: "\F0095";
+}
+.mdi-bed-queen::before {
+  content: "\F0096";
+}
+.mdi-bed-queen-outline::before {
+  content: "\F0097";
+}
+.mdi-bed-single::before {
+  content: "\F0098";
+}
+.mdi-bed-single-outline::before {
+  content: "\F0099";
+}
+.mdi-bee::before {
+  content: "\FFC1";
+}
+.mdi-bee-flower::before {
+  content: "\FFC2";
+}
+.mdi-beehive-outline::before {
+  content: "\F00F9";
+}
+.mdi-beer::before {
+  content: "\F098";
+}
+.mdi-beer-outline::before {
+  content: "\F0337";
+}
+.mdi-behance::before {
+  content: "\F099";
+}
+.mdi-bell::before {
+  content: "\F09A";
+}
+.mdi-bell-alert::before {
+  content: "\FD35";
+}
+.mdi-bell-alert-outline::before {
+  content: "\FE9E";
+}
+.mdi-bell-check::before {
+  content: "\F0210";
+}
+.mdi-bell-check-outline::before {
+  content: "\F0211";
+}
+.mdi-bell-circle::before {
+  content: "\FD36";
+}
+.mdi-bell-circle-outline::before {
+  content: "\FD37";
+}
+.mdi-bell-off::before {
+  content: "\F09B";
+}
+.mdi-bell-off-outline::before {
+  content: "\FA90";
+}
+.mdi-bell-outline::before {
+  content: "\F09C";
+}
+.mdi-bell-plus::before {
+  content: "\F09D";
+}
+.mdi-bell-plus-outline::before {
+  content: "\FA91";
+}
+.mdi-bell-ring::before {
+  content: "\F09E";
+}
+.mdi-bell-ring-outline::before {
+  content: "\F09F";
+}
+.mdi-bell-sleep::before {
+  content: "\F0A0";
+}
+.mdi-bell-sleep-outline::before {
+  content: "\FA92";
+}
+.mdi-beta::before {
+  content: "\F0A1";
+}
+.mdi-betamax::before {
+  content: "\F9CA";
+}
+.mdi-biathlon::before {
+  content: "\FDF7";
+}
+.mdi-bible::before {
+  content: "\F0A2";
+}
+.mdi-bicycle::before {
+  content: "\F00C7";
+}
+.mdi-bicycle-basket::before {
+  content: "\F0260";
+}
+.mdi-bike::before {
+  content: "\F0A3";
+}
+.mdi-bike-fast::before {
+  content: "\F014A";
+}
+.mdi-billboard::before {
+  content: "\F0032";
+}
+.mdi-billiards::before {
+  content: "\FB3D";
+}
+.mdi-billiards-rack::before {
+  content: "\FB3E";
+}
+.mdi-bing::before {
+  content: "\F0A4";
+}
+.mdi-binoculars::before {
+  content: "\F0A5";
+}
+.mdi-bio::before {
+  content: "\F0A6";
+}
+.mdi-biohazard::before {
+  content: "\F0A7";
+}
+.mdi-bitbucket::before {
+  content: "\F0A8";
+}
+.mdi-bitcoin::before {
+  content: "\F812";
+}
+.mdi-black-mesa::before {
+  content: "\F0A9";
+}
+.mdi-blackberry::before {
+  content: "\F0AA";
+}
+.mdi-blender::before {
+  content: "\FCC7";
+}
+.mdi-blender-software::before {
+  content: "\F0AB";
+}
+.mdi-blinds::before {
+  content: "\F0AC";
+}
+.mdi-blinds-open::before {
+  content: "\F0033";
+}
+.mdi-block-helper::before {
+  content: "\F0AD";
+}
+.mdi-blogger::before {
+  content: "\F0AE";
+}
+.mdi-blood-bag::before {
+  content: "\FCC8";
+}
+.mdi-bluetooth::before {
+  content: "\F0AF";
+}
+.mdi-bluetooth-audio::before {
+  content: "\F0B0";
+}
+.mdi-bluetooth-connect::before {
+  content: "\F0B1";
+}
+.mdi-bluetooth-off::before {
+  content: "\F0B2";
+}
+.mdi-bluetooth-settings::before {
+  content: "\F0B3";
+}
+.mdi-bluetooth-transfer::before {
+  content: "\F0B4";
+}
+.mdi-blur::before {
+  content: "\F0B5";
+}
+.mdi-blur-linear::before {
+  content: "\F0B6";
+}
+.mdi-blur-off::before {
+  content: "\F0B7";
+}
+.mdi-blur-radial::before {
+  content: "\F0B8";
+}
+.mdi-bolnisi-cross::before {
+  content: "\FCC9";
+}
+.mdi-bolt::before {
+  content: "\FD8F";
+}
+.mdi-bomb::before {
+  content: "\F690";
+}
+.mdi-bomb-off::before {
+  content: "\F6C4";
+}
+.mdi-bone::before {
+  content: "\F0B9";
+}
+.mdi-book::before {
+  content: "\F0BA";
+}
+.mdi-book-information-variant::before {
+  content: "\F009A";
+}
+.mdi-book-lock::before {
+  content: "\F799";
+}
+.mdi-book-lock-open::before {
+  content: "\F79A";
+}
+.mdi-book-minus::before {
+  content: "\F5D9";
+}
+.mdi-book-minus-multiple::before {
+  content: "\FA93";
+}
+.mdi-book-multiple::before {
+  content: "\F0BB";
+}
+.mdi-book-open::before {
+  content: "\F0BD";
+}
+.mdi-book-open-outline::before {
+  content: "\FB3F";
+}
+.mdi-book-open-page-variant::before {
+  content: "\F5DA";
+}
+.mdi-book-open-variant::before {
+  content: "\F0BE";
+}
+.mdi-book-outline::before {
+  content: "\FB40";
+}
+.mdi-book-play::before {
+  content: "\FE9F";
+}
+.mdi-book-play-outline::before {
+  content: "\FEA0";
+}
+.mdi-book-plus::before {
+  content: "\F5DB";
+}
+.mdi-book-plus-multiple::before {
+  content: "\FA94";
+}
+.mdi-book-remove::before {
+  content: "\FA96";
+}
+.mdi-book-remove-multiple::before {
+  content: "\FA95";
+}
+.mdi-book-search::before {
+  content: "\FEA1";
+}
+.mdi-book-search-outline::before {
+  content: "\FEA2";
+}
+.mdi-book-variant::before {
+  content: "\F0BF";
+}
+.mdi-book-variant-multiple::before {
+  content: "\F0BC";
+}
+.mdi-bookmark::before {
+  content: "\F0C0";
+}
+.mdi-bookmark-check::before {
+  content: "\F0C1";
+}
+.mdi-bookmark-check-outline::before {
+  content: "\F03A6";
+}
+.mdi-bookmark-minus::before {
+  content: "\F9CB";
+}
+.mdi-bookmark-minus-outline::before {
+  content: "\F9CC";
+}
+.mdi-bookmark-multiple::before {
+  content: "\FDF8";
+}
+.mdi-bookmark-multiple-outline::before {
+  content: "\FDF9";
+}
+.mdi-bookmark-music::before {
+  content: "\F0C2";
+}
+.mdi-bookmark-music-outline::before {
+  content: "\F03A4";
+}
+.mdi-bookmark-off::before {
+  content: "\F9CD";
+}
+.mdi-bookmark-off-outline::before {
+  content: "\F9CE";
+}
+.mdi-bookmark-outline::before {
+  content: "\F0C3";
+}
+.mdi-bookmark-plus::before {
+  content: "\F0C5";
+}
+.mdi-bookmark-plus-outline::before {
+  content: "\F0C4";
+}
+.mdi-bookmark-remove::before {
+  content: "\F0C6";
+}
+.mdi-bookmark-remove-outline::before {
+  content: "\F03A5";
+}
+.mdi-bookshelf::before {
+  content: "\F028A";
+}
+.mdi-boom-gate::before {
+  content: "\FEA3";
+}
+.mdi-boom-gate-alert::before {
+  content: "\FEA4";
+}
+.mdi-boom-gate-alert-outline::before {
+  content: "\FEA5";
+}
+.mdi-boom-gate-down::before {
+  content: "\FEA6";
+}
+.mdi-boom-gate-down-outline::before {
+  content: "\FEA7";
+}
+.mdi-boom-gate-outline::before {
+  content: "\FEA8";
+}
+.mdi-boom-gate-up::before {
+  content: "\FEA9";
+}
+.mdi-boom-gate-up-outline::before {
+  content: "\FEAA";
+}
+.mdi-boombox::before {
+  content: "\F5DC";
+}
+.mdi-boomerang::before {
+  content: "\F00FA";
+}
+.mdi-bootstrap::before {
+  content: "\F6C5";
+}
+.mdi-border-all::before {
+  content: "\F0C7";
+}
+.mdi-border-all-variant::before {
+  content: "\F8A0";
+}
+.mdi-border-bottom::before {
+  content: "\F0C8";
+}
+.mdi-border-bottom-variant::before {
+  content: "\F8A1";
+}
+.mdi-border-color::before {
+  content: "\F0C9";
+}
+.mdi-border-horizontal::before {
+  content: "\F0CA";
+}
+.mdi-border-inside::before {
+  content: "\F0CB";
+}
+.mdi-border-left::before {
+  content: "\F0CC";
+}
+.mdi-border-left-variant::before {
+  content: "\F8A2";
+}
+.mdi-border-none::before {
+  content: "\F0CD";
+}
+.mdi-border-none-variant::before {
+  content: "\F8A3";
+}
+.mdi-border-outside::before {
+  content: "\F0CE";
+}
+.mdi-border-right::before {
+  content: "\F0CF";
+}
+.mdi-border-right-variant::before {
+  content: "\F8A4";
+}
+.mdi-border-style::before {
+  content: "\F0D0";
+}
+.mdi-border-top::before {
+  content: "\F0D1";
+}
+.mdi-border-top-variant::before {
+  content: "\F8A5";
+}
+.mdi-border-vertical::before {
+  content: "\F0D2";
+}
+.mdi-bottle-soda::before {
+  content: "\F009B";
+}
+.mdi-bottle-soda-classic::before {
+  content: "\F009C";
+}
+.mdi-bottle-soda-classic-outline::before {
+  content: "\F038E";
+}
+.mdi-bottle-soda-outline::before {
+  content: "\F009D";
+}
+.mdi-bottle-tonic::before {
+  content: "\F0159";
+}
+.mdi-bottle-tonic-outline::before {
+  content: "\F015A";
+}
+.mdi-bottle-tonic-plus::before {
+  content: "\F015B";
+}
+.mdi-bottle-tonic-plus-outline::before {
+  content: "\F015C";
+}
+.mdi-bottle-tonic-skull::before {
+  content: "\F015D";
+}
+.mdi-bottle-tonic-skull-outline::before {
+  content: "\F015E";
+}
+.mdi-bottle-wine::before {
+  content: "\F853";
+}
+.mdi-bottle-wine-outline::before {
+  content: "\F033B";
+}
+.mdi-bow-tie::before {
+  content: "\F677";
+}
+.mdi-bowl::before {
+  content: "\F617";
+}
+.mdi-bowling::before {
+  content: "\F0D3";
+}
+.mdi-box::before {
+  content: "\F0D4";
+}
+.mdi-box-cutter::before {
+  content: "\F0D5";
+}
+.mdi-box-shadow::before {
+  content: "\F637";
+}
+.mdi-boxing-glove::before {
+  content: "\FB41";
+}
+.mdi-braille::before {
+  content: "\F9CF";
+}
+.mdi-brain::before {
+  content: "\F9D0";
+}
+.mdi-bread-slice::before {
+  content: "\FCCA";
+}
+.mdi-bread-slice-outline::before {
+  content: "\FCCB";
+}
+.mdi-bridge::before {
+  content: "\F618";
+}
+.mdi-briefcase::before {
+  content: "\F0D6";
+}
+.mdi-briefcase-account::before {
+  content: "\FCCC";
+}
+.mdi-briefcase-account-outline::before {
+  content: "\FCCD";
+}
+.mdi-briefcase-check::before {
+  content: "\F0D7";
+}
+.mdi-briefcase-check-outline::before {
+  content: "\F0349";
+}
+.mdi-briefcase-clock::before {
+  content: "\F00FB";
+}
+.mdi-briefcase-clock-outline::before {
+  content: "\F00FC";
+}
+.mdi-briefcase-download::before {
+  content: "\F0D8";
+}
+.mdi-briefcase-download-outline::before {
+  content: "\FC19";
+}
+.mdi-briefcase-edit::before {
+  content: "\FA97";
+}
+.mdi-briefcase-edit-outline::before {
+  content: "\FC1A";
+}
+.mdi-briefcase-minus::before {
+  content: "\FA29";
+}
+.mdi-briefcase-minus-outline::before {
+  content: "\FC1B";
+}
+.mdi-briefcase-outline::before {
+  content: "\F813";
+}
+.mdi-briefcase-plus::before {
+  content: "\FA2A";
+}
+.mdi-briefcase-plus-outline::before {
+  content: "\FC1C";
+}
+.mdi-briefcase-remove::before {
+  content: "\FA2B";
+}
+.mdi-briefcase-remove-outline::before {
+  content: "\FC1D";
+}
+.mdi-briefcase-search::before {
+  content: "\FA2C";
+}
+.mdi-briefcase-search-outline::before {
+  content: "\FC1E";
+}
+.mdi-briefcase-upload::before {
+  content: "\F0D9";
+}
+.mdi-briefcase-upload-outline::before {
+  content: "\FC1F";
+}
+.mdi-brightness-1::before {
+  content: "\F0DA";
+}
+.mdi-brightness-2::before {
+  content: "\F0DB";
+}
+.mdi-brightness-3::before {
+  content: "\F0DC";
+}
+.mdi-brightness-4::before {
+  content: "\F0DD";
+}
+.mdi-brightness-5::before {
+  content: "\F0DE";
+}
+.mdi-brightness-6::before {
+  content: "\F0DF";
+}
+.mdi-brightness-7::before {
+  content: "\F0E0";
+}
+.mdi-brightness-auto::before {
+  content: "\F0E1";
+}
+.mdi-brightness-percent::before {
+  content: "\FCCE";
+}
+.mdi-broom::before {
+  content: "\F0E2";
+}
+.mdi-brush::before {
+  content: "\F0E3";
+}
+.mdi-buddhism::before {
+  content: "\F94A";
+}
+.mdi-buffer::before {
+  content: "\F619";
+}
+.mdi-bug::before {
+  content: "\F0E4";
+}
+.mdi-bug-check::before {
+  content: "\FA2D";
+}
+.mdi-bug-check-outline::before {
+  content: "\FA2E";
+}
+.mdi-bug-outline::before {
+  content: "\FA2F";
+}
+.mdi-bugle::before {
+  content: "\FD90";
+}
+.mdi-bulldozer::before {
+  content: "\FB07";
+}
+.mdi-bullet::before {
+  content: "\FCCF";
+}
+.mdi-bulletin-board::before {
+  content: "\F0E5";
+}
+.mdi-bullhorn::before {
+  content: "\F0E6";
+}
+.mdi-bullhorn-outline::before {
+  content: "\FB08";
+}
+.mdi-bullseye::before {
+  content: "\F5DD";
+}
+.mdi-bullseye-arrow::before {
+  content: "\F8C8";
+}
+.mdi-bulma::before {
+  content: "\F0312";
+}
+.mdi-bunk-bed::before {
+  content: "\F032D";
+}
+.mdi-bus::before {
+  content: "\F0E7";
+}
+.mdi-bus-alert::before {
+  content: "\FA98";
+}
+.mdi-bus-articulated-end::before {
+  content: "\F79B";
+}
+.mdi-bus-articulated-front::before {
+  content: "\F79C";
+}
+.mdi-bus-clock::before {
+  content: "\F8C9";
+}
+.mdi-bus-double-decker::before {
+  content: "\F79D";
+}
+.mdi-bus-marker::before {
+  content: "\F023D";
+}
+.mdi-bus-multiple::before {
+  content: "\FF5C";
+}
+.mdi-bus-school::before {
+  content: "\F79E";
+}
+.mdi-bus-side::before {
+  content: "\F79F";
+}
+.mdi-bus-stop::before {
+  content: "\F0034";
+}
+.mdi-bus-stop-covered::before {
+  content: "\F0035";
+}
+.mdi-bus-stop-uncovered::before {
+  content: "\F0036";
+}
+.mdi-cached::before {
+  content: "\F0E8";
+}
+.mdi-cactus::before {
+  content: "\FD91";
+}
+.mdi-cake::before {
+  content: "\F0E9";
+}
+.mdi-cake-layered::before {
+  content: "\F0EA";
+}
+.mdi-cake-variant::before {
+  content: "\F0EB";
+}
+.mdi-calculator::before {
+  content: "\F0EC";
+}
+.mdi-calculator-variant::before {
+  content: "\FA99";
+}
+.mdi-calendar::before {
+  content: "\F0ED";
+}
+.mdi-calendar-account::before {
+  content: "\FEF4";
+}
+.mdi-calendar-account-outline::before {
+  content: "\FEF5";
+}
+.mdi-calendar-alert::before {
+  content: "\FA30";
+}
+.mdi-calendar-arrow-left::before {
+  content: "\F015F";
+}
+.mdi-calendar-arrow-right::before {
+  content: "\F0160";
+}
+.mdi-calendar-blank::before {
+  content: "\F0EE";
+}
+.mdi-calendar-blank-multiple::before {
+  content: "\F009E";
+}
+.mdi-calendar-blank-outline::before {
+  content: "\FB42";
+}
+.mdi-calendar-check::before {
+  content: "\F0EF";
+}
+.mdi-calendar-check-outline::before {
+  content: "\FC20";
+}
+.mdi-calendar-clock::before {
+  content: "\F0F0";
+}
+.mdi-calendar-edit::before {
+  content: "\F8A6";
+}
+.mdi-calendar-export::before {
+  content: "\FB09";
+}
+.mdi-calendar-heart::before {
+  content: "\F9D1";
+}
+.mdi-calendar-import::before {
+  content: "\FB0A";
+}
+.mdi-calendar-minus::before {
+  content: "\FD38";
+}
+.mdi-calendar-month::before {
+  content: "\FDFA";
+}
+.mdi-calendar-month-outline::before {
+  content: "\FDFB";
+}
+.mdi-calendar-multiple::before {
+  content: "\F0F1";
+}
+.mdi-calendar-multiple-check::before {
+  content: "\F0F2";
+}
+.mdi-calendar-multiselect::before {
+  content: "\FA31";
+}
+.mdi-calendar-outline::before {
+  content: "\FB43";
+}
+.mdi-calendar-plus::before {
+  content: "\F0F3";
+}
+.mdi-calendar-question::before {
+  content: "\F691";
+}
+.mdi-calendar-range::before {
+  content: "\F678";
+}
+.mdi-calendar-range-outline::before {
+  content: "\FB44";
+}
+.mdi-calendar-remove::before {
+  content: "\F0F4";
+}
+.mdi-calendar-remove-outline::before {
+  content: "\FC21";
+}
+.mdi-calendar-repeat::before {
+  content: "\FEAB";
+}
+.mdi-calendar-repeat-outline::before {
+  content: "\FEAC";
+}
+.mdi-calendar-search::before {
+  content: "\F94B";
+}
+.mdi-calendar-star::before {
+  content: "\F9D2";
+}
+.mdi-calendar-text::before {
+  content: "\F0F5";
+}
+.mdi-calendar-text-outline::before {
+  content: "\FC22";
+}
+.mdi-calendar-today::before {
+  content: "\F0F6";
+}
+.mdi-calendar-week::before {
+  content: "\FA32";
+}
+.mdi-calendar-week-begin::before {
+  content: "\FA33";
+}
+.mdi-calendar-weekend::before {
+  content: "\FEF6";
+}
+.mdi-calendar-weekend-outline::before {
+  content: "\FEF7";
+}
+.mdi-call-made::before {
+  content: "\F0F7";
+}
+.mdi-call-merge::before {
+  content: "\F0F8";
+}
+.mdi-call-missed::before {
+  content: "\F0F9";
+}
+.mdi-call-received::before {
+  content: "\F0FA";
+}
+.mdi-call-split::before {
+  content: "\F0FB";
+}
+.mdi-camcorder::before {
+  content: "\F0FC";
+}
+.mdi-camcorder-box::before {
+  content: "\F0FD";
+}
+.mdi-camcorder-box-off::before {
+  content: "\F0FE";
+}
+.mdi-camcorder-off::before {
+  content: "\F0FF";
+}
+.mdi-camera::before {
+  content: "\F100";
+}
+.mdi-camera-account::before {
+  content: "\F8CA";
+}
+.mdi-camera-burst::before {
+  content: "\F692";
+}
+.mdi-camera-control::before {
+  content: "\FB45";
+}
+.mdi-camera-enhance::before {
+  content: "\F101";
+}
+.mdi-camera-enhance-outline::before {
+  content: "\FB46";
+}
+.mdi-camera-front::before {
+  content: "\F102";
+}
+.mdi-camera-front-variant::before {
+  content: "\F103";
+}
+.mdi-camera-gopro::before {
+  content: "\F7A0";
+}
+.mdi-camera-image::before {
+  content: "\F8CB";
+}
+.mdi-camera-iris::before {
+  content: "\F104";
+}
+.mdi-camera-metering-center::before {
+  content: "\F7A1";
+}
+.mdi-camera-metering-matrix::before {
+  content: "\F7A2";
+}
+.mdi-camera-metering-partial::before {
+  content: "\F7A3";
+}
+.mdi-camera-metering-spot::before {
+  content: "\F7A4";
+}
+.mdi-camera-off::before {
+  content: "\F5DF";
+}
+.mdi-camera-outline::before {
+  content: "\FD39";
+}
+.mdi-camera-party-mode::before {
+  content: "\F105";
+}
+.mdi-camera-plus::before {
+  content: "\FEF8";
+}
+.mdi-camera-plus-outline::before {
+  content: "\FEF9";
+}
+.mdi-camera-rear::before {
+  content: "\F106";
+}
+.mdi-camera-rear-variant::before {
+  content: "\F107";
+}
+.mdi-camera-retake::before {
+  content: "\FDFC";
+}
+.mdi-camera-retake-outline::before {
+  content: "\FDFD";
+}
+.mdi-camera-switch::before {
+  content: "\F108";
+}
+.mdi-camera-timer::before {
+  content: "\F109";
+}
+.mdi-camera-wireless::before {
+  content: "\FD92";
+}
+.mdi-camera-wireless-outline::before {
+  content: "\FD93";
+}
+.mdi-campfire::before {
+  content: "\FEFA";
+}
+.mdi-cancel::before {
+  content: "\F739";
+}
+.mdi-candle::before {
+  content: "\F5E2";
+}
+.mdi-candycane::before {
+  content: "\F10A";
+}
+.mdi-cannabis::before {
+  content: "\F7A5";
+}
+.mdi-caps-lock::before {
+  content: "\FA9A";
+}
+.mdi-car::before {
+  content: "\F10B";
+}
+.mdi-car-2-plus::before {
+  content: "\F0037";
+}
+.mdi-car-3-plus::before {
+  content: "\F0038";
+}
+.mdi-car-back::before {
+  content: "\FDFE";
+}
+.mdi-car-battery::before {
+  content: "\F10C";
+}
+.mdi-car-brake-abs::before {
+  content: "\FC23";
+}
+.mdi-car-brake-alert::before {
+  content: "\FC24";
+}
+.mdi-car-brake-hold::before {
+  content: "\FD3A";
+}
+.mdi-car-brake-parking::before {
+  content: "\FD3B";
+}
+.mdi-car-brake-retarder::before {
+  content: "\F0039";
+}
+.mdi-car-child-seat::before {
+  content: "\FFC3";
+}
+.mdi-car-clutch::before {
+  content: "\F003A";
+}
+.mdi-car-connected::before {
+  content: "\F10D";
+}
+.mdi-car-convertible::before {
+  content: "\F7A6";
+}
+.mdi-car-coolant-level::before {
+  content: "\F003B";
+}
+.mdi-car-cruise-control::before {
+  content: "\FD3C";
+}
+.mdi-car-defrost-front::before {
+  content: "\FD3D";
+}
+.mdi-car-defrost-rear::before {
+  content: "\FD3E";
+}
+.mdi-car-door::before {
+  content: "\FB47";
+}
+.mdi-car-door-lock::before {
+  content: "\F00C8";
+}
+.mdi-car-electric::before {
+  content: "\FB48";
+}
+.mdi-car-esp::before {
+  content: "\FC25";
+}
+.mdi-car-estate::before {
+  content: "\F7A7";
+}
+.mdi-car-hatchback::before {
+  content: "\F7A8";
+}
+.mdi-car-info::before {
+  content: "\F01E9";
+}
+.mdi-car-key::before {
+  content: "\FB49";
+}
+.mdi-car-light-dimmed::before {
+  content: "\FC26";
+}
+.mdi-car-light-fog::before {
+  content: "\FC27";
+}
+.mdi-car-light-high::before {
+  content: "\FC28";
+}
+.mdi-car-limousine::before {
+  content: "\F8CC";
+}
+.mdi-car-multiple::before {
+  content: "\FB4A";
+}
+.mdi-car-off::before {
+  content: "\FDFF";
+}
+.mdi-car-parking-lights::before {
+  content: "\FD3F";
+}
+.mdi-car-pickup::before {
+  content: "\F7A9";
+}
+.mdi-car-seat::before {
+  content: "\FFC4";
+}
+.mdi-car-seat-cooler::before {
+  content: "\FFC5";
+}
+.mdi-car-seat-heater::before {
+  content: "\FFC6";
+}
+.mdi-car-shift-pattern::before {
+  content: "\FF5D";
+}
+.mdi-car-side::before {
+  content: "\F7AA";
+}
+.mdi-car-sports::before {
+  content: "\F7AB";
+}
+.mdi-car-tire-alert::before {
+  content: "\FC29";
+}
+.mdi-car-traction-control::before {
+  content: "\FD40";
+}
+.mdi-car-turbocharger::before {
+  content: "\F003C";
+}
+.mdi-car-wash::before {
+  content: "\F10E";
+}
+.mdi-car-windshield::before {
+  content: "\F003D";
+}
+.mdi-car-windshield-outline::before {
+  content: "\F003E";
+}
+.mdi-caravan::before {
+  content: "\F7AC";
+}
+.mdi-card::before {
+  content: "\FB4B";
+}
+.mdi-card-bulleted::before {
+  content: "\FB4C";
+}
+.mdi-card-bulleted-off::before {
+  content: "\FB4D";
+}
+.mdi-card-bulleted-off-outline::before {
+  content: "\FB4E";
+}
+.mdi-card-bulleted-outline::before {
+  content: "\FB4F";
+}
+.mdi-card-bulleted-settings::before {
+  content: "\FB50";
+}
+.mdi-card-bulleted-settings-outline::before {
+  content: "\FB51";
+}
+.mdi-card-outline::before {
+  content: "\FB52";
+}
+.mdi-card-plus::before {
+  content: "\F022A";
+}
+.mdi-card-plus-outline::before {
+  content: "\F022B";
+}
+.mdi-card-search::before {
+  content: "\F009F";
+}
+.mdi-card-search-outline::before {
+  content: "\F00A0";
+}
+.mdi-card-text::before {
+  content: "\FB53";
+}
+.mdi-card-text-outline::before {
+  content: "\FB54";
+}
+.mdi-cards::before {
+  content: "\F638";
+}
+.mdi-cards-club::before {
+  content: "\F8CD";
+}
+.mdi-cards-diamond::before {
+  content: "\F8CE";
+}
+.mdi-cards-diamond-outline::before {
+  content: "\F003F";
+}
+.mdi-cards-heart::before {
+  content: "\F8CF";
+}
+.mdi-cards-outline::before {
+  content: "\F639";
+}
+.mdi-cards-playing-outline::before {
+  content: "\F63A";
+}
+.mdi-cards-spade::before {
+  content: "\F8D0";
+}
+.mdi-cards-variant::before {
+  content: "\F6C6";
+}
+.mdi-carrot::before {
+  content: "\F10F";
+}
+.mdi-cart::before {
+  content: "\F110";
+}
+.mdi-cart-arrow-down::before {
+  content: "\FD42";
+}
+.mdi-cart-arrow-right::before {
+  content: "\FC2A";
+}
+.mdi-cart-arrow-up::before {
+  content: "\FD43";
+}
+.mdi-cart-minus::before {
+  content: "\FD44";
+}
+.mdi-cart-off::before {
+  content: "\F66B";
+}
+.mdi-cart-outline::before {
+  content: "\F111";
+}
+.mdi-cart-plus::before {
+  content: "\F112";
+}
+.mdi-cart-remove::before {
+  content: "\FD45";
+}
+.mdi-case-sensitive-alt::before {
+  content: "\F113";
+}
+.mdi-cash::before {
+  content: "\F114";
+}
+.mdi-cash-100::before {
+  content: "\F115";
+}
+.mdi-cash-marker::before {
+  content: "\FD94";
+}
+.mdi-cash-minus::before {
+  content: "\F028B";
+}
+.mdi-cash-multiple::before {
+  content: "\F116";
+}
+.mdi-cash-plus::before {
+  content: "\F028C";
+}
+.mdi-cash-refund::before {
+  content: "\FA9B";
+}
+.mdi-cash-register::before {
+  content: "\FCD0";
+}
+.mdi-cash-remove::before {
+  content: "\F028D";
+}
+.mdi-cash-usd::before {
+  content: "\F01A1";
+}
+.mdi-cash-usd-outline::before {
+  content: "\F117";
+}
+.mdi-cassette::before {
+  content: "\F9D3";
+}
+.mdi-cast::before {
+  content: "\F118";
+}
+.mdi-cast-audio::before {
+  content: "\F0040";
+}
+.mdi-cast-connected::before {
+  content: "\F119";
+}
+.mdi-cast-education::before {
+  content: "\FE6D";
+}
+.mdi-cast-off::before {
+  content: "\F789";
+}
+.mdi-castle::before {
+  content: "\F11A";
+}
+.mdi-cat::before {
+  content: "\F11B";
+}
+.mdi-cctv::before {
+  content: "\F7AD";
+}
+.mdi-ceiling-light::before {
+  content: "\F768";
+}
+.mdi-cellphone::before {
+  content: "\F11C";
+}
+.mdi-cellphone-android::before {
+  content: "\F11D";
+}
+.mdi-cellphone-arrow-down::before {
+  content: "\F9D4";
+}
+.mdi-cellphone-basic::before {
+  content: "\F11E";
+}
+.mdi-cellphone-dock::before {
+  content: "\F11F";
+}
+.mdi-cellphone-erase::before {
+  content: "\F94C";
+}
+.mdi-cellphone-information::before {
+  content: "\FF5E";
+}
+.mdi-cellphone-iphone::before {
+  content: "\F120";
+}
+.mdi-cellphone-key::before {
+  content: "\F94D";
+}
+.mdi-cellphone-link::before {
+  content: "\F121";
+}
+.mdi-cellphone-link-off::before {
+  content: "\F122";
+}
+.mdi-cellphone-lock::before {
+  content: "\F94E";
+}
+.mdi-cellphone-message::before {
+  content: "\F8D2";
+}
+.mdi-cellphone-message-off::before {
+  content: "\F00FD";
+}
+.mdi-cellphone-nfc::before {
+  content: "\FEAD";
+}
+.mdi-cellphone-nfc-off::before {
+  content: "\F0303";
+}
+.mdi-cellphone-off::before {
+  content: "\F94F";
+}
+.mdi-cellphone-play::before {
+  content: "\F0041";
+}
+.mdi-cellphone-screenshot::before {
+  content: "\FA34";
+}
+.mdi-cellphone-settings::before {
+  content: "\F123";
+}
+.mdi-cellphone-settings-variant::before {
+  content: "\F950";
+}
+.mdi-cellphone-sound::before {
+  content: "\F951";
+}
+.mdi-cellphone-text::before {
+  content: "\F8D1";
+}
+.mdi-cellphone-wireless::before {
+  content: "\F814";
+}
+.mdi-celtic-cross::before {
+  content: "\FCD1";
+}
+.mdi-centos::before {
+  content: "\F0145";
+}
+.mdi-certificate::before {
+  content: "\F124";
+}
+.mdi-certificate-outline::before {
+  content: "\F01B3";
+}
+.mdi-chair-rolling::before {
+  content: "\FFBA";
+}
+.mdi-chair-school::before {
+  content: "\F125";
+}
+.mdi-charity::before {
+  content: "\FC2B";
+}
+.mdi-chart-arc::before {
+  content: "\F126";
+}
+.mdi-chart-areaspline::before {
+  content: "\F127";
+}
+.mdi-chart-areaspline-variant::before {
+  content: "\FEAE";
+}
+.mdi-chart-bar::before {
+  content: "\F128";
+}
+.mdi-chart-bar-stacked::before {
+  content: "\F769";
+}
+.mdi-chart-bell-curve::before {
+  content: "\FC2C";
+}
+.mdi-chart-bell-curve-cumulative::before {
+  content: "\FFC7";
+}
+.mdi-chart-bubble::before {
+  content: "\F5E3";
+}
+.mdi-chart-donut::before {
+  content: "\F7AE";
+}
+.mdi-chart-donut-variant::before {
+  content: "\F7AF";
+}
+.mdi-chart-gantt::before {
+  content: "\F66C";
+}
+.mdi-chart-histogram::before {
+  content: "\F129";
+}
+.mdi-chart-line::before {
+  content: "\F12A";
+}
+.mdi-chart-line-stacked::before {
+  content: "\F76A";
+}
+.mdi-chart-line-variant::before {
+  content: "\F7B0";
+}
+.mdi-chart-multiline::before {
+  content: "\F8D3";
+}
+.mdi-chart-multiple::before {
+  content: "\F023E";
+}
+.mdi-chart-pie::before {
+  content: "\F12B";
+}
+.mdi-chart-ppf::before {
+  content: "\F03AB";
+}
+.mdi-chart-scatter-plot::before {
+  content: "\FEAF";
+}
+.mdi-chart-scatter-plot-hexbin::before {
+  content: "\F66D";
+}
+.mdi-chart-snakey::before {
+  content: "\F020A";
+}
+.mdi-chart-snakey-variant::before {
+  content: "\F020B";
+}
+.mdi-chart-timeline::before {
+  content: "\F66E";
+}
+.mdi-chart-timeline-variant::before {
+  content: "\FEB0";
+}
+.mdi-chart-tree::before {
+  content: "\FEB1";
+}
+.mdi-chat::before {
+  content: "\FB55";
+}
+.mdi-chat-alert::before {
+  content: "\FB56";
+}
+.mdi-chat-alert-outline::before {
+  content: "\F02F4";
+}
+.mdi-chat-outline::before {
+  content: "\FEFB";
+}
+.mdi-chat-processing::before {
+  content: "\FB57";
+}
+.mdi-chat-processing-outline::before {
+  content: "\F02F5";
+}
+.mdi-chat-sleep::before {
+  content: "\F02FC";
+}
+.mdi-chat-sleep-outline::before {
+  content: "\F02FD";
+}
+.mdi-check::before {
+  content: "\F12C";
+}
+.mdi-check-all::before {
+  content: "\F12D";
+}
+.mdi-check-bold::before {
+  content: "\FE6E";
+}
+.mdi-check-box-multiple-outline::before {
+  content: "\FC2D";
+}
+.mdi-check-box-outline::before {
+  content: "\FC2E";
+}
+.mdi-check-circle::before {
+  content: "\F5E0";
+}
+.mdi-check-circle-outline::before {
+  content: "\F5E1";
+}
+.mdi-check-decagram::before {
+  content: "\F790";
+}
+.mdi-check-network::before {
+  content: "\FC2F";
+}
+.mdi-check-network-outline::before {
+  content: "\FC30";
+}
+.mdi-check-outline::before {
+  content: "\F854";
+}
+.mdi-check-underline::before {
+  content: "\FE70";
+}
+.mdi-check-underline-circle::before {
+  content: "\FE71";
+}
+.mdi-check-underline-circle-outline::before {
+  content: "\FE72";
+}
+.mdi-checkbook::before {
+  content: "\FA9C";
+}
+.mdi-checkbox-blank::before {
+  content: "\F12E";
+}
+.mdi-checkbox-blank-circle::before {
+  content: "\F12F";
+}
+.mdi-checkbox-blank-circle-outline::before {
+  content: "\F130";
+}
+.mdi-checkbox-blank-off::before {
+  content: "\F0317";
+}
+.mdi-checkbox-blank-off-outline::before {
+  content: "\F0318";
+}
+.mdi-checkbox-blank-outline::before {
+  content: "\F131";
+}
+.mdi-checkbox-intermediate::before {
+  content: "\F855";
+}
+.mdi-checkbox-marked::before {
+  content: "\F132";
+}
+.mdi-checkbox-marked-circle::before {
+  content: "\F133";
+}
+.mdi-checkbox-marked-circle-outline::before {
+  content: "\F134";
+}
+.mdi-checkbox-marked-outline::before {
+  content: "\F135";
+}
+.mdi-checkbox-multiple-blank::before {
+  content: "\F136";
+}
+.mdi-checkbox-multiple-blank-circle::before {
+  content: "\F63B";
+}
+.mdi-checkbox-multiple-blank-circle-outline::before {
+  content: "\F63C";
+}
+.mdi-checkbox-multiple-blank-outline::before {
+  content: "\F137";
+}
+.mdi-checkbox-multiple-marked::before {
+  content: "\F138";
+}
+.mdi-checkbox-multiple-marked-circle::before {
+  content: "\F63D";
+}
+.mdi-checkbox-multiple-marked-circle-outline::before {
+  content: "\F63E";
+}
+.mdi-checkbox-multiple-marked-outline::before {
+  content: "\F139";
+}
+.mdi-checkerboard::before {
+  content: "\F13A";
+}
+.mdi-checkerboard-minus::before {
+  content: "\F022D";
+}
+.mdi-checkerboard-plus::before {
+  content: "\F022C";
+}
+.mdi-checkerboard-remove::before {
+  content: "\F022E";
+}
+.mdi-cheese::before {
+  content: "\F02E4";
+}
+.mdi-chef-hat::before {
+  content: "\FB58";
+}
+.mdi-chemical-weapon::before {
+  content: "\F13B";
+}
+.mdi-chess-bishop::before {
+  content: "\F85B";
+}
+.mdi-chess-king::before {
+  content: "\F856";
+}
+.mdi-chess-knight::before {
+  content: "\F857";
+}
+.mdi-chess-pawn::before {
+  content: "\F858";
+}
+.mdi-chess-queen::before {
+  content: "\F859";
+}
+.mdi-chess-rook::before {
+  content: "\F85A";
+}
+.mdi-chevron-double-down::before {
+  content: "\F13C";
+}
+.mdi-chevron-double-left::before {
+  content: "\F13D";
+}
+.mdi-chevron-double-right::before {
+  content: "\F13E";
+}
+.mdi-chevron-double-up::before {
+  content: "\F13F";
+}
+.mdi-chevron-down::before {
+  content: "\F140";
+}
+.mdi-chevron-down-box::before {
+  content: "\F9D5";
+}
+.mdi-chevron-down-box-outline::before {
+  content: "\F9D6";
+}
+.mdi-chevron-down-circle::before {
+  content: "\FB0B";
+}
+.mdi-chevron-down-circle-outline::before {
+  content: "\FB0C";
+}
+.mdi-chevron-left::before {
+  content: "\F141";
+}
+.mdi-chevron-left-box::before {
+  content: "\F9D7";
+}
+.mdi-chevron-left-box-outline::before {
+  content: "\F9D8";
+}
+.mdi-chevron-left-circle::before {
+  content: "\FB0D";
+}
+.mdi-chevron-left-circle-outline::before {
+  content: "\FB0E";
+}
+.mdi-chevron-right::before {
+  content: "\F142";
+}
+.mdi-chevron-right-box::before {
+  content: "\F9D9";
+}
+.mdi-chevron-right-box-outline::before {
+  content: "\F9DA";
+}
+.mdi-chevron-right-circle::before {
+  content: "\FB0F";
+}
+.mdi-chevron-right-circle-outline::before {
+  content: "\FB10";
+}
+.mdi-chevron-triple-down::before {
+  content: "\FD95";
+}
+.mdi-chevron-triple-left::before {
+  content: "\FD96";
+}
+.mdi-chevron-triple-right::before {
+  content: "\FD97";
+}
+.mdi-chevron-triple-up::before {
+  content: "\FD98";
+}
+.mdi-chevron-up::before {
+  content: "\F143";
+}
+.mdi-chevron-up-box::before {
+  content: "\F9DB";
+}
+.mdi-chevron-up-box-outline::before {
+  content: "\F9DC";
+}
+.mdi-chevron-up-circle::before {
+  content: "\FB11";
+}
+.mdi-chevron-up-circle-outline::before {
+  content: "\FB12";
+}
+.mdi-chili-hot::before {
+  content: "\F7B1";
+}
+.mdi-chili-medium::before {
+  content: "\F7B2";
+}
+.mdi-chili-mild::before {
+  content: "\F7B3";
+}
+.mdi-chip::before {
+  content: "\F61A";
+}
+.mdi-christianity::before {
+  content: "\F952";
+}
+.mdi-christianity-outline::before {
+  content: "\FCD2";
+}
+.mdi-church::before {
+  content: "\F144";
+}
+.mdi-cigar::before {
+  content: "\F01B4";
+}
+.mdi-circle::before {
+  content: "\F764";
+}
+.mdi-circle-double::before {
+  content: "\FEB2";
+}
+.mdi-circle-edit-outline::before {
+  content: "\F8D4";
+}
+.mdi-circle-expand::before {
+  content: "\FEB3";
+}
+.mdi-circle-medium::before {
+  content: "\F9DD";
+}
+.mdi-circle-off-outline::before {
+  content: "\F00FE";
+}
+.mdi-circle-outline::before {
+  content: "\F765";
+}
+.mdi-circle-slice-1::before {
+  content: "\FA9D";
+}
+.mdi-circle-slice-2::before {
+  content: "\FA9E";
+}
+.mdi-circle-slice-3::before {
+  content: "\FA9F";
+}
+.mdi-circle-slice-4::before {
+  content: "\FAA0";
+}
+.mdi-circle-slice-5::before {
+  content: "\FAA1";
+}
+.mdi-circle-slice-6::before {
+  content: "\FAA2";
+}
+.mdi-circle-slice-7::before {
+  content: "\FAA3";
+}
+.mdi-circle-slice-8::before {
+  content: "\FAA4";
+}
+.mdi-circle-small::before {
+  content: "\F9DE";
+}
+.mdi-circular-saw::before {
+  content: "\FE73";
+}
+.mdi-cisco-webex::before {
+  content: "\F145";
+}
+.mdi-city::before {
+  content: "\F146";
+}
+.mdi-city-variant::before {
+  content: "\FA35";
+}
+.mdi-city-variant-outline::before {
+  content: "\FA36";
+}
+.mdi-clipboard::before {
+  content: "\F147";
+}
+.mdi-clipboard-account::before {
+  content: "\F148";
+}
+.mdi-clipboard-account-outline::before {
+  content: "\FC31";
+}
+.mdi-clipboard-alert::before {
+  content: "\F149";
+}
+.mdi-clipboard-alert-outline::before {
+  content: "\FCD3";
+}
+.mdi-clipboard-arrow-down::before {
+  content: "\F14A";
+}
+.mdi-clipboard-arrow-down-outline::before {
+  content: "\FC32";
+}
+.mdi-clipboard-arrow-left::before {
+  content: "\F14B";
+}
+.mdi-clipboard-arrow-left-outline::before {
+  content: "\FCD4";
+}
+.mdi-clipboard-arrow-right::before {
+  content: "\FCD5";
+}
+.mdi-clipboard-arrow-right-outline::before {
+  content: "\FCD6";
+}
+.mdi-clipboard-arrow-up::before {
+  content: "\FC33";
+}
+.mdi-clipboard-arrow-up-outline::before {
+  content: "\FC34";
+}
+.mdi-clipboard-check::before {
+  content: "\F14C";
+}
+.mdi-clipboard-check-multiple::before {
+  content: "\F028E";
+}
+.mdi-clipboard-check-multiple-outline::before {
+  content: "\F028F";
+}
+.mdi-clipboard-check-outline::before {
+  content: "\F8A7";
+}
+.mdi-clipboard-file::before {
+  content: "\F0290";
+}
+.mdi-clipboard-file-outline::before {
+  content: "\F0291";
+}
+.mdi-clipboard-flow::before {
+  content: "\F6C7";
+}
+.mdi-clipboard-flow-outline::before {
+  content: "\F0142";
+}
+.mdi-clipboard-list::before {
+  content: "\F00FF";
+}
+.mdi-clipboard-list-outline::before {
+  content: "\F0100";
+}
+.mdi-clipboard-multiple::before {
+  content: "\F0292";
+}
+.mdi-clipboard-multiple-outline::before {
+  content: "\F0293";
+}
+.mdi-clipboard-outline::before {
+  content: "\F14D";
+}
+.mdi-clipboard-play::before {
+  content: "\FC35";
+}
+.mdi-clipboard-play-multiple::before {
+  content: "\F0294";
+}
+.mdi-clipboard-play-multiple-outline::before {
+  content: "\F0295";
+}
+.mdi-clipboard-play-outline::before {
+  content: "\FC36";
+}
+.mdi-clipboard-plus::before {
+  content: "\F750";
+}
+.mdi-clipboard-plus-outline::before {
+  content: "\F034A";
+}
+.mdi-clipboard-pulse::before {
+  content: "\F85C";
+}
+.mdi-clipboard-pulse-outline::before {
+  content: "\F85D";
+}
+.mdi-clipboard-text::before {
+  content: "\F14E";
+}
+.mdi-clipboard-text-multiple::before {
+  content: "\F0296";
+}
+.mdi-clipboard-text-multiple-outline::before {
+  content: "\F0297";
+}
+.mdi-clipboard-text-outline::before {
+  content: "\FA37";
+}
+.mdi-clipboard-text-play::before {
+  content: "\FC37";
+}
+.mdi-clipboard-text-play-outline::before {
+  content: "\FC38";
+}
+.mdi-clippy::before {
+  content: "\F14F";
+}
+.mdi-clock::before {
+  content: "\F953";
+}
+.mdi-clock-alert::before {
+  content: "\F954";
+}
+.mdi-clock-alert-outline::before {
+  content: "\F5CE";
+}
+.mdi-clock-check::before {
+  content: "\FFC8";
+}
+.mdi-clock-check-outline::before {
+  content: "\FFC9";
+}
+.mdi-clock-digital::before {
+  content: "\FEB4";
+}
+.mdi-clock-end::before {
+  content: "\F151";
+}
+.mdi-clock-fast::before {
+  content: "\F152";
+}
+.mdi-clock-in::before {
+  content: "\F153";
+}
+.mdi-clock-out::before {
+  content: "\F154";
+}
+.mdi-clock-outline::before {
+  content: "\F150";
+}
+.mdi-clock-start::before {
+  content: "\F155";
+}
+.mdi-close::before {
+  content: "\F156";
+}
+.mdi-close-box::before {
+  content: "\F157";
+}
+.mdi-close-box-multiple::before {
+  content: "\FC39";
+}
+.mdi-close-box-multiple-outline::before {
+  content: "\FC3A";
+}
+.mdi-close-box-outline::before {
+  content: "\F158";
+}
+.mdi-close-circle::before {
+  content: "\F159";
+}
+.mdi-close-circle-outline::before {
+  content: "\F15A";
+}
+.mdi-close-network::before {
+  content: "\F15B";
+}
+.mdi-close-network-outline::before {
+  content: "\FC3B";
+}
+.mdi-close-octagon::before {
+  content: "\F15C";
+}
+.mdi-close-octagon-outline::before {
+  content: "\F15D";
+}
+.mdi-close-outline::before {
+  content: "\F6C8";
+}
+.mdi-closed-caption::before {
+  content: "\F15E";
+}
+.mdi-closed-caption-outline::before {
+  content: "\FD99";
+}
+.mdi-cloud::before {
+  content: "\F15F";
+}
+.mdi-cloud-alert::before {
+  content: "\F9DF";
+}
+.mdi-cloud-braces::before {
+  content: "\F7B4";
+}
+.mdi-cloud-check::before {
+  content: "\F160";
+}
+.mdi-cloud-check-outline::before {
+  content: "\F02F7";
+}
+.mdi-cloud-circle::before {
+  content: "\F161";
+}
+.mdi-cloud-download::before {
+  content: "\F162";
+}
+.mdi-cloud-download-outline::before {
+  content: "\FB59";
+}
+.mdi-cloud-lock::before {
+  content: "\F021C";
+}
+.mdi-cloud-lock-outline::before {
+  content: "\F021D";
+}
+.mdi-cloud-off-outline::before {
+  content: "\F164";
+}
+.mdi-cloud-outline::before {
+  content: "\F163";
+}
+.mdi-cloud-print::before {
+  content: "\F165";
+}
+.mdi-cloud-print-outline::before {
+  content: "\F166";
+}
+.mdi-cloud-question::before {
+  content: "\FA38";
+}
+.mdi-cloud-search::before {
+  content: "\F955";
+}
+.mdi-cloud-search-outline::before {
+  content: "\F956";
+}
+.mdi-cloud-sync::before {
+  content: "\F63F";
+}
+.mdi-cloud-sync-outline::before {
+  content: "\F0301";
+}
+.mdi-cloud-tags::before {
+  content: "\F7B5";
+}
+.mdi-cloud-upload::before {
+  content: "\F167";
+}
+.mdi-cloud-upload-outline::before {
+  content: "\FB5A";
+}
+.mdi-clover::before {
+  content: "\F815";
+}
+.mdi-coach-lamp::before {
+  content: "\F0042";
+}
+.mdi-coat-rack::before {
+  content: "\F00C9";
+}
+.mdi-code-array::before {
+  content: "\F168";
+}
+.mdi-code-braces::before {
+  content: "\F169";
+}
+.mdi-code-braces-box::before {
+  content: "\F0101";
+}
+.mdi-code-brackets::before {
+  content: "\F16A";
+}
+.mdi-code-equal::before {
+  content: "\F16B";
+}
+.mdi-code-greater-than::before {
+  content: "\F16C";
+}
+.mdi-code-greater-than-or-equal::before {
+  content: "\F16D";
+}
+.mdi-code-less-than::before {
+  content: "\F16E";
+}
+.mdi-code-less-than-or-equal::before {
+  content: "\F16F";
+}
+.mdi-code-not-equal::before {
+  content: "\F170";
+}
+.mdi-code-not-equal-variant::before {
+  content: "\F171";
+}
+.mdi-code-parentheses::before {
+  content: "\F172";
+}
+.mdi-code-parentheses-box::before {
+  content: "\F0102";
+}
+.mdi-code-string::before {
+  content: "\F173";
+}
+.mdi-code-tags::before {
+  content: "\F174";
+}
+.mdi-code-tags-check::before {
+  content: "\F693";
+}
+.mdi-codepen::before {
+  content: "\F175";
+}
+.mdi-coffee::before {
+  content: "\F176";
+}
+.mdi-coffee-maker::before {
+  content: "\F00CA";
+}
+.mdi-coffee-off::before {
+  content: "\FFCA";
+}
+.mdi-coffee-off-outline::before {
+  content: "\FFCB";
+}
+.mdi-coffee-outline::before {
+  content: "\F6C9";
+}
+.mdi-coffee-to-go::before {
+  content: "\F177";
+}
+.mdi-coffee-to-go-outline::before {
+  content: "\F0339";
+}
+.mdi-coffin::before {
+  content: "\FB5B";
+}
+.mdi-cog-clockwise::before {
+  content: "\F0208";
+}
+.mdi-cog-counterclockwise::before {
+  content: "\F0209";
+}
+.mdi-cogs::before {
+  content: "\F8D5";
+}
+.mdi-coin::before {
+  content: "\F0196";
+}
+.mdi-coin-outline::before {
+  content: "\F178";
+}
+.mdi-coins::before {
+  content: "\F694";
+}
+.mdi-collage::before {
+  content: "\F640";
+}
+.mdi-collapse-all::before {
+  content: "\FAA5";
+}
+.mdi-collapse-all-outline::before {
+  content: "\FAA6";
+}
+.mdi-color-helper::before {
+  content: "\F179";
+}
+.mdi-comma::before {
+  content: "\FE74";
+}
+.mdi-comma-box::before {
+  content: "\FE75";
+}
+.mdi-comma-box-outline::before {
+  content: "\FE76";
+}
+.mdi-comma-circle::before {
+  content: "\FE77";
+}
+.mdi-comma-circle-outline::before {
+  content: "\FE78";
+}
+.mdi-comment::before {
+  content: "\F17A";
+}
+.mdi-comment-account::before {
+  content: "\F17B";
+}
+.mdi-comment-account-outline::before {
+  content: "\F17C";
+}
+.mdi-comment-alert::before {
+  content: "\F17D";
+}
+.mdi-comment-alert-outline::before {
+  content: "\F17E";
+}
+.mdi-comment-arrow-left::before {
+  content: "\F9E0";
+}
+.mdi-comment-arrow-left-outline::before {
+  content: "\F9E1";
+}
+.mdi-comment-arrow-right::before {
+  content: "\F9E2";
+}
+.mdi-comment-arrow-right-outline::before {
+  content: "\F9E3";
+}
+.mdi-comment-check::before {
+  content: "\F17F";
+}
+.mdi-comment-check-outline::before {
+  content: "\F180";
+}
+.mdi-comment-edit::before {
+  content: "\F01EA";
+}
+.mdi-comment-edit-outline::before {
+  content: "\F02EF";
+}
+.mdi-comment-eye::before {
+  content: "\FA39";
+}
+.mdi-comment-eye-outline::before {
+  content: "\FA3A";
+}
+.mdi-comment-multiple::before {
+  content: "\F85E";
+}
+.mdi-comment-multiple-outline::before {
+  content: "\F181";
+}
+.mdi-comment-outline::before {
+  content: "\F182";
+}
+.mdi-comment-plus::before {
+  content: "\F9E4";
+}
+.mdi-comment-plus-outline::before {
+  content: "\F183";
+}
+.mdi-comment-processing::before {
+  content: "\F184";
+}
+.mdi-comment-processing-outline::before {
+  content: "\F185";
+}
+.mdi-comment-question::before {
+  content: "\F816";
+}
+.mdi-comment-question-outline::before {
+  content: "\F186";
+}
+.mdi-comment-quote::before {
+  content: "\F0043";
+}
+.mdi-comment-quote-outline::before {
+  content: "\F0044";
+}
+.mdi-comment-remove::before {
+  content: "\F5DE";
+}
+.mdi-comment-remove-outline::before {
+  content: "\F187";
+}
+.mdi-comment-search::before {
+  content: "\FA3B";
+}
+.mdi-comment-search-outline::before {
+  content: "\FA3C";
+}
+.mdi-comment-text::before {
+  content: "\F188";
+}
+.mdi-comment-text-multiple::before {
+  content: "\F85F";
+}
+.mdi-comment-text-multiple-outline::before {
+  content: "\F860";
+}
+.mdi-comment-text-outline::before {
+  content: "\F189";
+}
+.mdi-compare::before {
+  content: "\F18A";
+}
+.mdi-compass::before {
+  content: "\F18B";
+}
+.mdi-compass-off::before {
+  content: "\FB5C";
+}
+.mdi-compass-off-outline::before {
+  content: "\FB5D";
+}
+.mdi-compass-outline::before {
+  content: "\F18C";
+}
+.mdi-compass-rose::before {
+  content: "\F03AD";
+}
+.mdi-concourse-ci::before {
+  content: "\F00CB";
+}
+.mdi-console::before {
+  content: "\F18D";
+}
+.mdi-console-line::before {
+  content: "\F7B6";
+}
+.mdi-console-network::before {
+  content: "\F8A8";
+}
+.mdi-console-network-outline::before {
+  content: "\FC3C";
+}
+.mdi-consolidate::before {
+  content: "\F0103";
+}
+.mdi-contact-mail::before {
+  content: "\F18E";
+}
+.mdi-contact-mail-outline::before {
+  content: "\FEB5";
+}
+.mdi-contact-phone::before {
+  content: "\FEB6";
+}
+.mdi-contact-phone-outline::before {
+  content: "\FEB7";
+}
+.mdi-contactless-payment::before {
+  content: "\FD46";
+}
+.mdi-contacts::before {
+  content: "\F6CA";
+}
+.mdi-contain::before {
+  content: "\FA3D";
+}
+.mdi-contain-end::before {
+  content: "\FA3E";
+}
+.mdi-contain-start::before {
+  content: "\FA3F";
+}
+.mdi-content-copy::before {
+  content: "\F18F";
+}
+.mdi-content-cut::before {
+  content: "\F190";
+}
+.mdi-content-duplicate::before {
+  content: "\F191";
+}
+.mdi-content-paste::before {
+  content: "\F192";
+}
+.mdi-content-save::before {
+  content: "\F193";
+}
+.mdi-content-save-alert::before {
+  content: "\FF5F";
+}
+.mdi-content-save-alert-outline::before {
+  content: "\FF60";
+}
+.mdi-content-save-all::before {
+  content: "\F194";
+}
+.mdi-content-save-all-outline::before {
+  content: "\FF61";
+}
+.mdi-content-save-edit::before {
+  content: "\FCD7";
+}
+.mdi-content-save-edit-outline::before {
+  content: "\FCD8";
+}
+.mdi-content-save-move::before {
+  content: "\FE79";
+}
+.mdi-content-save-move-outline::before {
+  content: "\FE7A";
+}
+.mdi-content-save-outline::before {
+  content: "\F817";
+}
+.mdi-content-save-settings::before {
+  content: "\F61B";
+}
+.mdi-content-save-settings-outline::before {
+  content: "\FB13";
+}
+.mdi-contrast::before {
+  content: "\F195";
+}
+.mdi-contrast-box::before {
+  content: "\F196";
+}
+.mdi-contrast-circle::before {
+  content: "\F197";
+}
+.mdi-controller-classic::before {
+  content: "\FB5E";
+}
+.mdi-controller-classic-outline::before {
+  content: "\FB5F";
+}
+.mdi-cookie::before {
+  content: "\F198";
+}
+.mdi-coolant-temperature::before {
+  content: "\F3C8";
+}
+.mdi-copyright::before {
+  content: "\F5E6";
+}
+.mdi-cordova::before {
+  content: "\F957";
+}
+.mdi-corn::before {
+  content: "\F7B7";
+}
+.mdi-counter::before {
+  content: "\F199";
+}
+.mdi-cow::before {
+  content: "\F19A";
+}
+.mdi-cowboy::before {
+  content: "\FEB8";
+}
+.mdi-cpu-32-bit::before {
+  content: "\FEFC";
+}
+.mdi-cpu-64-bit::before {
+  content: "\FEFD";
+}
+.mdi-crane::before {
+  content: "\F861";
+}
+.mdi-creation::before {
+  content: "\F1C9";
+}
+.mdi-creative-commons::before {
+  content: "\FD47";
+}
+.mdi-credit-card::before {
+  content: "\F0010";
+}
+.mdi-credit-card-clock::before {
+  content: "\FEFE";
+}
+.mdi-credit-card-clock-outline::before {
+  content: "\FFBC";
+}
+.mdi-credit-card-marker::before {
+  content: "\F6A7";
+}
+.mdi-credit-card-marker-outline::before {
+  content: "\FD9A";
+}
+.mdi-credit-card-minus::before {
+  content: "\FFCC";
+}
+.mdi-credit-card-minus-outline::before {
+  content: "\FFCD";
+}
+.mdi-credit-card-multiple::before {
+  content: "\F0011";
+}
+.mdi-credit-card-multiple-outline::before {
+  content: "\F19C";
+}
+.mdi-credit-card-off::before {
+  content: "\F0012";
+}
+.mdi-credit-card-off-outline::before {
+  content: "\F5E4";
+}
+.mdi-credit-card-outline::before {
+  content: "\F19B";
+}
+.mdi-credit-card-plus::before {
+  content: "\F0013";
+}
+.mdi-credit-card-plus-outline::before {
+  content: "\F675";
+}
+.mdi-credit-card-refund::before {
+  content: "\F0014";
+}
+.mdi-credit-card-refund-outline::before {
+  content: "\FAA7";
+}
+.mdi-credit-card-remove::before {
+  content: "\FFCE";
+}
+.mdi-credit-card-remove-outline::before {
+  content: "\FFCF";
+}
+.mdi-credit-card-scan::before {
+  content: "\F0015";
+}
+.mdi-credit-card-scan-outline::before {
+  content: "\F19D";
+}
+.mdi-credit-card-settings::before {
+  content: "\F0016";
+}
+.mdi-credit-card-settings-outline::before {
+  content: "\F8D6";
+}
+.mdi-credit-card-wireless::before {
+  content: "\F801";
+}
+.mdi-credit-card-wireless-outline::before {
+  content: "\FD48";
+}
+.mdi-cricket::before {
+  content: "\FD49";
+}
+.mdi-crop::before {
+  content: "\F19E";
+}
+.mdi-crop-free::before {
+  content: "\F19F";
+}
+.mdi-crop-landscape::before {
+  content: "\F1A0";
+}
+.mdi-crop-portrait::before {
+  content: "\F1A1";
+}
+.mdi-crop-rotate::before {
+  content: "\F695";
+}
+.mdi-crop-square::before {
+  content: "\F1A2";
+}
+.mdi-crosshairs::before {
+  content: "\F1A3";
+}
+.mdi-crosshairs-gps::before {
+  content: "\F1A4";
+}
+.mdi-crosshairs-off::before {
+  content: "\FF62";
+}
+.mdi-crosshairs-question::before {
+  content: "\F0161";
+}
+.mdi-crown::before {
+  content: "\F1A5";
+}
+.mdi-crown-outline::before {
+  content: "\F01FB";
+}
+.mdi-cryengine::before {
+  content: "\F958";
+}
+.mdi-crystal-ball::before {
+  content: "\FB14";
+}
+.mdi-cube::before {
+  content: "\F1A6";
+}
+.mdi-cube-outline::before {
+  content: "\F1A7";
+}
+.mdi-cube-scan::before {
+  content: "\FB60";
+}
+.mdi-cube-send::before {
+  content: "\F1A8";
+}
+.mdi-cube-unfolded::before {
+  content: "\F1A9";
+}
+.mdi-cup::before {
+  content: "\F1AA";
+}
+.mdi-cup-off::before {
+  content: "\F5E5";
+}
+.mdi-cup-off-outline::before {
+  content: "\F03A8";
+}
+.mdi-cup-outline::before {
+  content: "\F033A";
+}
+.mdi-cup-water::before {
+  content: "\F1AB";
+}
+.mdi-cupboard::before {
+  content: "\FF63";
+}
+.mdi-cupboard-outline::before {
+  content: "\FF64";
+}
+.mdi-cupcake::before {
+  content: "\F959";
+}
+.mdi-curling::before {
+  content: "\F862";
+}
+.mdi-currency-bdt::before {
+  content: "\F863";
+}
+.mdi-currency-brl::before {
+  content: "\FB61";
+}
+.mdi-currency-btc::before {
+  content: "\F1AC";
+}
+.mdi-currency-cny::before {
+  content: "\F7B9";
+}
+.mdi-currency-eth::before {
+  content: "\F7BA";
+}
+.mdi-currency-eur::before {
+  content: "\F1AD";
+}
+.mdi-currency-eur-off::before {
+  content: "\F0340";
+}
+.mdi-currency-gbp::before {
+  content: "\F1AE";
+}
+.mdi-currency-ils::before {
+  content: "\FC3D";
+}
+.mdi-currency-inr::before {
+  content: "\F1AF";
+}
+.mdi-currency-jpy::before {
+  content: "\F7BB";
+}
+.mdi-currency-krw::before {
+  content: "\F7BC";
+}
+.mdi-currency-kzt::before {
+  content: "\F864";
+}
+.mdi-currency-ngn::before {
+  content: "\F1B0";
+}
+.mdi-currency-php::before {
+  content: "\F9E5";
+}
+.mdi-currency-rial::before {
+  content: "\FEB9";
+}
+.mdi-currency-rub::before {
+  content: "\F1B1";
+}
+.mdi-currency-sign::before {
+  content: "\F7BD";
+}
+.mdi-currency-try::before {
+  content: "\F1B2";
+}
+.mdi-currency-twd::before {
+  content: "\F7BE";
+}
+.mdi-currency-usd::before {
+  content: "\F1B3";
+}
+.mdi-currency-usd-off::before {
+  content: "\F679";
+}
+.mdi-current-ac::before {
+  content: "\F95A";
+}
+.mdi-current-dc::before {
+  content: "\F95B";
+}
+.mdi-cursor-default::before {
+  content: "\F1B4";
+}
+.mdi-cursor-default-click::before {
+  content: "\FCD9";
+}
+.mdi-cursor-default-click-outline::before {
+  content: "\FCDA";
+}
+.mdi-cursor-default-gesture::before {
+  content: "\F0152";
+}
+.mdi-cursor-default-gesture-outline::before {
+  content: "\F0153";
+}
+.mdi-cursor-default-outline::before {
+  content: "\F1B5";
+}
+.mdi-cursor-move::before {
+  content: "\F1B6";
+}
+.mdi-cursor-pointer::before {
+  content: "\F1B7";
+}
+.mdi-cursor-text::before {
+  content: "\F5E7";
+}
+.mdi-database::before {
+  content: "\F1B8";
+}
+.mdi-database-check::before {
+  content: "\FAA8";
+}
+.mdi-database-edit::before {
+  content: "\FB62";
+}
+.mdi-database-export::before {
+  content: "\F95D";
+}
+.mdi-database-import::before {
+  content: "\F95C";
+}
+.mdi-database-lock::before {
+  content: "\FAA9";
+}
+.mdi-database-marker::before {
+  content: "\F0321";
+}
+.mdi-database-minus::before {
+  content: "\F1B9";
+}
+.mdi-database-plus::before {
+  content: "\F1BA";
+}
+.mdi-database-refresh::before {
+  content: "\FCDB";
+}
+.mdi-database-remove::before {
+  content: "\FCDC";
+}
+.mdi-database-search::before {
+  content: "\F865";
+}
+.mdi-database-settings::before {
+  content: "\FCDD";
+}
+.mdi-death-star::before {
+  content: "\F8D7";
+}
+.mdi-death-star-variant::before {
+  content: "\F8D8";
+}
+.mdi-deathly-hallows::before {
+  content: "\FB63";
+}
+.mdi-debian::before {
+  content: "\F8D9";
+}
+.mdi-debug-step-into::before {
+  content: "\F1BB";
+}
+.mdi-debug-step-out::before {
+  content: "\F1BC";
+}
+.mdi-debug-step-over::before {
+  content: "\F1BD";
+}
+.mdi-decagram::before {
+  content: "\F76B";
+}
+.mdi-decagram-outline::before {
+  content: "\F76C";
+}
+.mdi-decimal::before {
+  content: "\F00CC";
+}
+.mdi-decimal-comma::before {
+  content: "\F00CD";
+}
+.mdi-decimal-comma-decrease::before {
+  content: "\F00CE";
+}
+.mdi-decimal-comma-increase::before {
+  content: "\F00CF";
+}
+.mdi-decimal-decrease::before {
+  content: "\F1BE";
+}
+.mdi-decimal-increase::before {
+  content: "\F1BF";
+}
+.mdi-delete::before {
+  content: "\F1C0";
+}
+.mdi-delete-alert::before {
+  content: "\F00D0";
+}
+.mdi-delete-alert-outline::before {
+  content: "\F00D1";
+}
+.mdi-delete-circle::before {
+  content: "\F682";
+}
+.mdi-delete-circle-outline::before {
+  content: "\FB64";
+}
+.mdi-delete-empty::before {
+  content: "\F6CB";
+}
+.mdi-delete-empty-outline::before {
+  content: "\FEBA";
+}
+.mdi-delete-forever::before {
+  content: "\F5E8";
+}
+.mdi-delete-forever-outline::before {
+  content: "\FB65";
+}
+.mdi-delete-off::before {
+  content: "\F00D2";
+}
+.mdi-delete-off-outline::before {
+  content: "\F00D3";
+}
+.mdi-delete-outline::before {
+  content: "\F9E6";
+}
+.mdi-delete-restore::before {
+  content: "\F818";
+}
+.mdi-delete-sweep::before {
+  content: "\F5E9";
+}
+.mdi-delete-sweep-outline::before {
+  content: "\FC3E";
+}
+.mdi-delete-variant::before {
+  content: "\F1C1";
+}
+.mdi-delta::before {
+  content: "\F1C2";
+}
+.mdi-desk::before {
+  content: "\F0264";
+}
+.mdi-desk-lamp::before {
+  content: "\F95E";
+}
+.mdi-deskphone::before {
+  content: "\F1C3";
+}
+.mdi-desktop-classic::before {
+  content: "\F7BF";
+}
+.mdi-desktop-mac::before {
+  content: "\F1C4";
+}
+.mdi-desktop-mac-dashboard::before {
+  content: "\F9E7";
+}
+.mdi-desktop-tower::before {
+  content: "\F1C5";
+}
+.mdi-desktop-tower-monitor::before {
+  content: "\FAAA";
+}
+.mdi-details::before {
+  content: "\F1C6";
+}
+.mdi-dev-to::before {
+  content: "\FD4A";
+}
+.mdi-developer-board::before {
+  content: "\F696";
+}
+.mdi-deviantart::before {
+  content: "\F1C7";
+}
+.mdi-devices::before {
+  content: "\FFD0";
+}
+.mdi-diabetes::before {
+  content: "\F0151";
+}
+.mdi-dialpad::before {
+  content: "\F61C";
+}
+.mdi-diameter::before {
+  content: "\FC3F";
+}
+.mdi-diameter-outline::before {
+  content: "\FC40";
+}
+.mdi-diameter-variant::before {
+  content: "\FC41";
+}
+.mdi-diamond::before {
+  content: "\FB66";
+}
+.mdi-diamond-outline::before {
+  content: "\FB67";
+}
+.mdi-diamond-stone::before {
+  content: "\F1C8";
+}
+.mdi-dice-1::before {
+  content: "\F1CA";
+}
+.mdi-dice-1-outline::before {
+  content: "\F0175";
+}
+.mdi-dice-2::before {
+  content: "\F1CB";
+}
+.mdi-dice-2-outline::before {
+  content: "\F0176";
+}
+.mdi-dice-3::before {
+  content: "\F1CC";
+}
+.mdi-dice-3-outline::before {
+  content: "\F0177";
+}
+.mdi-dice-4::before {
+  content: "\F1CD";
+}
+.mdi-dice-4-outline::before {
+  content: "\F0178";
+}
+.mdi-dice-5::before {
+  content: "\F1CE";
+}
+.mdi-dice-5-outline::before {
+  content: "\F0179";
+}
+.mdi-dice-6::before {
+  content: "\F1CF";
+}
+.mdi-dice-6-outline::before {
+  content: "\F017A";
+}
+.mdi-dice-d10::before {
+  content: "\F017E";
+}
+.mdi-dice-d10-outline::before {
+  content: "\F76E";
+}
+.mdi-dice-d12::before {
+  content: "\F017F";
+}
+.mdi-dice-d12-outline::before {
+  content: "\F866";
+}
+.mdi-dice-d20::before {
+  content: "\F0180";
+}
+.mdi-dice-d20-outline::before {
+  content: "\F5EA";
+}
+.mdi-dice-d4::before {
+  content: "\F017B";
+}
+.mdi-dice-d4-outline::before {
+  content: "\F5EB";
+}
+.mdi-dice-d6::before {
+  content: "\F017C";
+}
+.mdi-dice-d6-outline::before {
+  content: "\F5EC";
+}
+.mdi-dice-d8::before {
+  content: "\F017D";
+}
+.mdi-dice-d8-outline::before {
+  content: "\F5ED";
+}
+.mdi-dice-multiple::before {
+  content: "\F76D";
+}
+.mdi-dice-multiple-outline::before {
+  content: "\F0181";
+}
+.mdi-dictionary::before {
+  content: "\F61D";
+}
+.mdi-digital-ocean::before {
+  content: "\F0262";
+}
+.mdi-dip-switch::before {
+  content: "\F7C0";
+}
+.mdi-directions::before {
+  content: "\F1D0";
+}
+.mdi-directions-fork::before {
+  content: "\F641";
+}
+.mdi-disc::before {
+  content: "\F5EE";
+}
+.mdi-disc-alert::before {
+  content: "\F1D1";
+}
+.mdi-disc-player::before {
+  content: "\F95F";
+}
+.mdi-discord::before {
+  content: "\F66F";
+}
+.mdi-dishwasher::before {
+  content: "\FAAB";
+}
+.mdi-dishwasher-alert::before {
+  content: "\F01E3";
+}
+.mdi-dishwasher-off::before {
+  content: "\F01E4";
+}
+.mdi-disqus::before {
+  content: "\F1D2";
+}
+.mdi-disqus-outline::before {
+  content: "\F1D3";
+}
+.mdi-distribute-horizontal-center::before {
+  content: "\F01F4";
+}
+.mdi-distribute-horizontal-left::before {
+  content: "\F01F3";
+}
+.mdi-distribute-horizontal-right::before {
+  content: "\F01F5";
+}
+.mdi-distribute-vertical-bottom::before {
+  content: "\F01F6";
+}
+.mdi-distribute-vertical-center::before {
+  content: "\F01F7";
+}
+.mdi-distribute-vertical-top::before {
+  content: "\F01F8";
+}
+.mdi-diving-flippers::before {
+  content: "\FD9B";
+}
+.mdi-diving-helmet::before {
+  content: "\FD9C";
+}
+.mdi-diving-scuba::before {
+  content: "\FD9D";
+}
+.mdi-diving-scuba-flag::before {
+  content: "\FD9E";
+}
+.mdi-diving-scuba-tank::before {
+  content: "\FD9F";
+}
+.mdi-diving-scuba-tank-multiple::before {
+  content: "\FDA0";
+}
+.mdi-diving-snorkel::before {
+  content: "\FDA1";
+}
+.mdi-division::before {
+  content: "\F1D4";
+}
+.mdi-division-box::before {
+  content: "\F1D5";
+}
+.mdi-dlna::before {
+  content: "\FA40";
+}
+.mdi-dna::before {
+  content: "\F683";
+}
+.mdi-dns::before {
+  content: "\F1D6";
+}
+.mdi-dns-outline::before {
+  content: "\FB68";
+}
+.mdi-do-not-disturb::before {
+  content: "\F697";
+}
+.mdi-do-not-disturb-off::before {
+  content: "\F698";
+}
+.mdi-dock-bottom::before {
+  content: "\F00D4";
+}
+.mdi-dock-left::before {
+  content: "\F00D5";
+}
+.mdi-dock-right::before {
+  content: "\F00D6";
+}
+.mdi-dock-window::before {
+  content: "\F00D7";
+}
+.mdi-docker::before {
+  content: "\F867";
+}
+.mdi-doctor::before {
+  content: "\FA41";
+}
+.mdi-dog::before {
+  content: "\FA42";
+}
+.mdi-dog-service::before {
+  content: "\FAAC";
+}
+.mdi-dog-side::before {
+  content: "\FA43";
+}
+.mdi-dolby::before {
+  content: "\F6B2";
+}
+.mdi-dolly::before {
+  content: "\FEBB";
+}
+.mdi-domain::before {
+  content: "\F1D7";
+}
+.mdi-domain-off::before {
+  content: "\FD4B";
+}
+.mdi-domain-plus::before {
+  content: "\F00D8";
+}
+.mdi-domain-remove::before {
+  content: "\F00D9";
+}
+.mdi-domino-mask::before {
+  content: "\F0045";
+}
+.mdi-donkey::before {
+  content: "\F7C1";
+}
+.mdi-door::before {
+  content: "\F819";
+}
+.mdi-door-closed::before {
+  content: "\F81A";
+}
+.mdi-door-closed-lock::before {
+  content: "\F00DA";
+}
+.mdi-door-open::before {
+  content: "\F81B";
+}
+.mdi-doorbell::before {
+  content: "\F0311";
+}
+.mdi-doorbell-video::before {
+  content: "\F868";
+}
+.mdi-dot-net::before {
+  content: "\FAAD";
+}
+.mdi-dots-horizontal::before {
+  content: "\F1D8";
+}
+.mdi-dots-horizontal-circle::before {
+  content: "\F7C2";
+}
+.mdi-dots-horizontal-circle-outline::before {
+  content: "\FB69";
+}
+.mdi-dots-vertical::before {
+  content: "\F1D9";
+}
+.mdi-dots-vertical-circle::before {
+  content: "\F7C3";
+}
+.mdi-dots-vertical-circle-outline::before {
+  content: "\FB6A";
+}
+.mdi-douban::before {
+  content: "\F699";
+}
+.mdi-download::before {
+  content: "\F1DA";
+}
+.mdi-download-lock::before {
+  content: "\F034B";
+}
+.mdi-download-lock-outline::before {
+  content: "\F034C";
+}
+.mdi-download-multiple::before {
+  content: "\F9E8";
+}
+.mdi-download-network::before {
+  content: "\F6F3";
+}
+.mdi-download-network-outline::before {
+  content: "\FC42";
+}
+.mdi-download-off::before {
+  content: "\F00DB";
+}
+.mdi-download-off-outline::before {
+  content: "\F00DC";
+}
+.mdi-download-outline::before {
+  content: "\FB6B";
+}
+.mdi-drag::before {
+  content: "\F1DB";
+}
+.mdi-drag-horizontal::before {
+  content: "\F1DC";
+}
+.mdi-drag-horizontal-variant::before {
+  content: "\F031B";
+}
+.mdi-drag-variant::before {
+  content: "\FB6C";
+}
+.mdi-drag-vertical::before {
+  content: "\F1DD";
+}
+.mdi-drag-vertical-variant::before {
+  content: "\F031C";
+}
+.mdi-drama-masks::before {
+  content: "\FCDE";
+}
+.mdi-draw::before {
+  content: "\FF66";
+}
+.mdi-drawing::before {
+  content: "\F1DE";
+}
+.mdi-drawing-box::before {
+  content: "\F1DF";
+}
+.mdi-dresser::before {
+  content: "\FF67";
+}
+.mdi-dresser-outline::before {
+  content: "\FF68";
+}
+.mdi-dribbble::before {
+  content: "\F1E0";
+}
+.mdi-dribbble-box::before {
+  content: "\F1E1";
+}
+.mdi-drone::before {
+  content: "\F1E2";
+}
+.mdi-dropbox::before {
+  content: "\F1E3";
+}
+.mdi-drupal::before {
+  content: "\F1E4";
+}
+.mdi-duck::before {
+  content: "\F1E5";
+}
+.mdi-dumbbell::before {
+  content: "\F1E6";
+}
+.mdi-dump-truck::before {
+  content: "\FC43";
+}
+.mdi-ear-hearing::before {
+  content: "\F7C4";
+}
+.mdi-ear-hearing-off::before {
+  content: "\FA44";
+}
+.mdi-earth::before {
+  content: "\F1E7";
+}
+.mdi-earth-arrow-right::before {
+  content: "\F033C";
+}
+.mdi-earth-box::before {
+  content: "\F6CC";
+}
+.mdi-earth-box-off::before {
+  content: "\F6CD";
+}
+.mdi-earth-off::before {
+  content: "\F1E8";
+}
+.mdi-edge::before {
+  content: "\F1E9";
+}
+.mdi-edge-legacy::before {
+  content: "\F027B";
+}
+.mdi-egg::before {
+  content: "\FAAE";
+}
+.mdi-egg-easter::before {
+  content: "\FAAF";
+}
+.mdi-eight-track::before {
+  content: "\F9E9";
+}
+.mdi-eject::before {
+  content: "\F1EA";
+}
+.mdi-eject-outline::before {
+  content: "\FB6D";
+}
+.mdi-electric-switch::before {
+  content: "\FEBC";
+}
+.mdi-electric-switch-closed::before {
+  content: "\F0104";
+}
+.mdi-electron-framework::before {
+  content: "\F0046";
+}
+.mdi-elephant::before {
+  content: "\F7C5";
+}
+.mdi-elevation-decline::before {
+  content: "\F1EB";
+}
+.mdi-elevation-rise::before {
+  content: "\F1EC";
+}
+.mdi-elevator::before {
+  content: "\F1ED";
+}
+.mdi-elevator-down::before {
+  content: "\F02ED";
+}
+.mdi-elevator-passenger::before {
+  content: "\F03AC";
+}
+.mdi-elevator-up::before {
+  content: "\F02EC";
+}
+.mdi-ellipse::before {
+  content: "\FEBD";
+}
+.mdi-ellipse-outline::before {
+  content: "\FEBE";
+}
+.mdi-email::before {
+  content: "\F1EE";
+}
+.mdi-email-alert::before {
+  content: "\F6CE";
+}
+.mdi-email-alert-outline::before {
+  content: "\FD1E";
+}
+.mdi-email-box::before {
+  content: "\FCDF";
+}
+.mdi-email-check::before {
+  content: "\FAB0";
+}
+.mdi-email-check-outline::before {
+  content: "\FAB1";
+}
+.mdi-email-edit::before {
+  content: "\FF00";
+}
+.mdi-email-edit-outline::before {
+  content: "\FF01";
+}
+.mdi-email-lock::before {
+  content: "\F1F1";
+}
+.mdi-email-mark-as-unread::before {
+  content: "\FB6E";
+}
+.mdi-email-minus::before {
+  content: "\FF02";
+}
+.mdi-email-minus-outline::before {
+  content: "\FF03";
+}
+.mdi-email-multiple::before {
+  content: "\FF04";
+}
+.mdi-email-multiple-outline::before {
+  content: "\FF05";
+}
+.mdi-email-newsletter::before {
+  content: "\FFD1";
+}
+.mdi-email-open::before {
+  content: "\F1EF";
+}
+.mdi-email-open-multiple::before {
+  content: "\FF06";
+}
+.mdi-email-open-multiple-outline::before {
+  content: "\FF07";
+}
+.mdi-email-open-outline::before {
+  content: "\F5EF";
+}
+.mdi-email-outline::before {
+  content: "\F1F0";
+}
+.mdi-email-plus::before {
+  content: "\F9EA";
+}
+.mdi-email-plus-outline::before {
+  content: "\F9EB";
+}
+.mdi-email-receive::before {
+  content: "\F0105";
+}
+.mdi-email-receive-outline::before {
+  content: "\F0106";
+}
+.mdi-email-search::before {
+  content: "\F960";
+}
+.mdi-email-search-outline::before {
+  content: "\F961";
+}
+.mdi-email-send::before {
+  content: "\F0107";
+}
+.mdi-email-send-outline::before {
+  content: "\F0108";
+}
+.mdi-email-sync::before {
+  content: "\F02F2";
+}
+.mdi-email-sync-outline::before {
+  content: "\F02F3";
+}
+.mdi-email-variant::before {
+  content: "\F5F0";
+}
+.mdi-ember::before {
+  content: "\FB15";
+}
+.mdi-emby::before {
+  content: "\F6B3";
+}
+.mdi-emoticon::before {
+  content: "\FC44";
+}
+.mdi-emoticon-angry::before {
+  content: "\FC45";
+}
+.mdi-emoticon-angry-outline::before {
+  content: "\FC46";
+}
+.mdi-emoticon-confused::before {
+  content: "\F0109";
+}
+.mdi-emoticon-confused-outline::before {
+  content: "\F010A";
+}
+.mdi-emoticon-cool::before {
+  content: "\FC47";
+}
+.mdi-emoticon-cool-outline::before {
+  content: "\F1F3";
+}
+.mdi-emoticon-cry::before {
+  content: "\FC48";
+}
+.mdi-emoticon-cry-outline::before {
+  content: "\FC49";
+}
+.mdi-emoticon-dead::before {
+  content: "\FC4A";
+}
+.mdi-emoticon-dead-outline::before {
+  content: "\F69A";
+}
+.mdi-emoticon-devil::before {
+  content: "\FC4B";
+}
+.mdi-emoticon-devil-outline::before {
+  content: "\F1F4";
+}
+.mdi-emoticon-excited::before {
+  content: "\FC4C";
+}
+.mdi-emoticon-excited-outline::before {
+  content: "\F69B";
+}
+.mdi-emoticon-frown::before {
+  content: "\FF69";
+}
+.mdi-emoticon-frown-outline::before {
+  content: "\FF6A";
+}
+.mdi-emoticon-happy::before {
+  content: "\FC4D";
+}
+.mdi-emoticon-happy-outline::before {
+  content: "\F1F5";
+}
+.mdi-emoticon-kiss::before {
+  content: "\FC4E";
+}
+.mdi-emoticon-kiss-outline::before {
+  content: "\FC4F";
+}
+.mdi-emoticon-lol::before {
+  content: "\F023F";
+}
+.mdi-emoticon-lol-outline::before {
+  content: "\F0240";
+}
+.mdi-emoticon-neutral::before {
+  content: "\FC50";
+}
+.mdi-emoticon-neutral-outline::before {
+  content: "\F1F6";
+}
+.mdi-emoticon-outline::before {
+  content: "\F1F2";
+}
+.mdi-emoticon-poop::before {
+  content: "\F1F7";
+}
+.mdi-emoticon-poop-outline::before {
+  content: "\FC51";
+}
+.mdi-emoticon-sad::before {
+  content: "\FC52";
+}
+.mdi-emoticon-sad-outline::before {
+  content: "\F1F8";
+}
+.mdi-emoticon-tongue::before {
+  content: "\F1F9";
+}
+.mdi-emoticon-tongue-outline::before {
+  content: "\FC53";
+}
+.mdi-emoticon-wink::before {
+  content: "\FC54";
+}
+.mdi-emoticon-wink-outline::before {
+  content: "\FC55";
+}
+.mdi-engine::before {
+  content: "\F1FA";
+}
+.mdi-engine-off::before {
+  content: "\FA45";
+}
+.mdi-engine-off-outline::before {
+  content: "\FA46";
+}
+.mdi-engine-outline::before {
+  content: "\F1FB";
+}
+.mdi-epsilon::before {
+  content: "\F010B";
+}
+.mdi-equal::before {
+  content: "\F1FC";
+}
+.mdi-equal-box::before {
+  content: "\F1FD";
+}
+.mdi-equalizer::before {
+  content: "\FEBF";
+}
+.mdi-equalizer-outline::before {
+  content: "\FEC0";
+}
+.mdi-eraser::before {
+  content: "\F1FE";
+}
+.mdi-eraser-variant::before {
+  content: "\F642";
+}
+.mdi-escalator::before {
+  content: "\F1FF";
+}
+.mdi-escalator-down::before {
+  content: "\F02EB";
+}
+.mdi-escalator-up::before {
+  content: "\F02EA";
+}
+.mdi-eslint::before {
+  content: "\FC56";
+}
+.mdi-et::before {
+  content: "\FAB2";
+}
+.mdi-ethereum::before {
+  content: "\F869";
+}
+.mdi-ethernet::before {
+  content: "\F200";
+}
+.mdi-ethernet-cable::before {
+  content: "\F201";
+}
+.mdi-ethernet-cable-off::before {
+  content: "\F202";
+}
+.mdi-etsy::before {
+  content: "\F203";
+}
+.mdi-ev-station::before {
+  content: "\F5F1";
+}
+.mdi-eventbrite::before {
+  content: "\F7C6";
+}
+.mdi-evernote::before {
+  content: "\F204";
+}
+.mdi-excavator::before {
+  content: "\F0047";
+}
+.mdi-exclamation::before {
+  content: "\F205";
+}
+.mdi-exclamation-thick::before {
+  content: "\F0263";
+}
+.mdi-exit-run::before {
+  content: "\FA47";
+}
+.mdi-exit-to-app::before {
+  content: "\F206";
+}
+.mdi-expand-all::before {
+  content: "\FAB3";
+}
+.mdi-expand-all-outline::before {
+  content: "\FAB4";
+}
+.mdi-expansion-card::before {
+  content: "\F8AD";
+}
+.mdi-expansion-card-variant::before {
+  content: "\FFD2";
+}
+.mdi-exponent::before {
+  content: "\F962";
+}
+.mdi-exponent-box::before {
+  content: "\F963";
+}
+.mdi-export::before {
+  content: "\F207";
+}
+.mdi-export-variant::before {
+  content: "\FB6F";
+}
+.mdi-eye::before {
+  content: "\F208";
+}
+.mdi-eye-check::before {
+  content: "\FCE0";
+}
+.mdi-eye-check-outline::before {
+  content: "\FCE1";
+}
+.mdi-eye-circle::before {
+  content: "\FB70";
+}
+.mdi-eye-circle-outline::before {
+  content: "\FB71";
+}
+.mdi-eye-minus::before {
+  content: "\F0048";
+}
+.mdi-eye-minus-outline::before {
+  content: "\F0049";
+}
+.mdi-eye-off::before {
+  content: "\F209";
+}
+.mdi-eye-off-outline::before {
+  content: "\F6D0";
+}
+.mdi-eye-outline::before {
+  content: "\F6CF";
+}
+.mdi-eye-plus::before {
+  content: "\F86A";
+}
+.mdi-eye-plus-outline::before {
+  content: "\F86B";
+}
+.mdi-eye-settings::before {
+  content: "\F86C";
+}
+.mdi-eye-settings-outline::before {
+  content: "\F86D";
+}
+.mdi-eyedropper::before {
+  content: "\F20A";
+}
+.mdi-eyedropper-variant::before {
+  content: "\F20B";
+}
+.mdi-face::before {
+  content: "\F643";
+}
+.mdi-face-agent::before {
+  content: "\FD4C";
+}
+.mdi-face-outline::before {
+  content: "\FB72";
+}
+.mdi-face-profile::before {
+  content: "\F644";
+}
+.mdi-face-profile-woman::before {
+  content: "\F00A1";
+}
+.mdi-face-recognition::before {
+  content: "\FC57";
+}
+.mdi-face-woman::before {
+  content: "\F00A2";
+}
+.mdi-face-woman-outline::before {
+  content: "\F00A3";
+}
+.mdi-facebook::before {
+  content: "\F20C";
+}
+.mdi-facebook-box::before {
+  content: "\F20D";
+}
+.mdi-facebook-messenger::before {
+  content: "\F20E";
+}
+.mdi-facebook-workplace::before {
+  content: "\FB16";
+}
+.mdi-factory::before {
+  content: "\F20F";
+}
+.mdi-fan::before {
+  content: "\F210";
+}
+.mdi-fan-off::before {
+  content: "\F81C";
+}
+.mdi-fast-forward::before {
+  content: "\F211";
+}
+.mdi-fast-forward-10::before {
+  content: "\FD4D";
+}
+.mdi-fast-forward-30::before {
+  content: "\FCE2";
+}
+.mdi-fast-forward-5::before {
+  content: "\F0223";
+}
+.mdi-fast-forward-outline::before {
+  content: "\F6D1";
+}
+.mdi-fax::before {
+  content: "\F212";
+}
+.mdi-feather::before {
+  content: "\F6D2";
+}
+.mdi-feature-search::before {
+  content: "\FA48";
+}
+.mdi-feature-search-outline::before {
+  content: "\FA49";
+}
+.mdi-fedora::before {
+  content: "\F8DA";
+}
+.mdi-ferris-wheel::before {
+  content: "\FEC1";
+}
+.mdi-ferry::before {
+  content: "\F213";
+}
+.mdi-file::before {
+  content: "\F214";
+}
+.mdi-file-account::before {
+  content: "\F73A";
+}
+.mdi-file-account-outline::before {
+  content: "\F004A";
+}
+.mdi-file-alert::before {
+  content: "\FA4A";
+}
+.mdi-file-alert-outline::before {
+  content: "\FA4B";
+}
+.mdi-file-cabinet::before {
+  content: "\FAB5";
+}
+.mdi-file-cad::before {
+  content: "\FF08";
+}
+.mdi-file-cad-box::before {
+  content: "\FF09";
+}
+.mdi-file-cancel::before {
+  content: "\FDA2";
+}
+.mdi-file-cancel-outline::before {
+  content: "\FDA3";
+}
+.mdi-file-certificate::before {
+  content: "\F01B1";
+}
+.mdi-file-certificate-outline::before {
+  content: "\F01B2";
+}
+.mdi-file-chart::before {
+  content: "\F215";
+}
+.mdi-file-chart-outline::before {
+  content: "\F004B";
+}
+.mdi-file-check::before {
+  content: "\F216";
+}
+.mdi-file-check-outline::before {
+  content: "\FE7B";
+}
+.mdi-file-clock::before {
+  content: "\F030C";
+}
+.mdi-file-clock-outline::before {
+  content: "\F030D";
+}
+.mdi-file-cloud::before {
+  content: "\F217";
+}
+.mdi-file-cloud-outline::before {
+  content: "\F004C";
+}
+.mdi-file-code::before {
+  content: "\F22E";
+}
+.mdi-file-code-outline::before {
+  content: "\F004D";
+}
+.mdi-file-compare::before {
+  content: "\F8A9";
+}
+.mdi-file-delimited::before {
+  content: "\F218";
+}
+.mdi-file-delimited-outline::before {
+  content: "\FEC2";
+}
+.mdi-file-document::before {
+  content: "\F219";
+}
+.mdi-file-document-box::before {
+  content: "\F21A";
+}
+.mdi-file-document-box-check::before {
+  content: "\FEC3";
+}
+.mdi-file-document-box-check-outline::before {
+  content: "\FEC4";
+}
+.mdi-file-document-box-minus::before {
+  content: "\FEC5";
+}
+.mdi-file-document-box-minus-outline::before {
+  content: "\FEC6";
+}
+.mdi-file-document-box-multiple::before {
+  content: "\FAB6";
+}
+.mdi-file-document-box-multiple-outline::before {
+  content: "\FAB7";
+}
+.mdi-file-document-box-outline::before {
+  content: "\F9EC";
+}
+.mdi-file-document-box-plus::before {
+  content: "\FEC7";
+}
+.mdi-file-document-box-plus-outline::before {
+  content: "\FEC8";
+}
+.mdi-file-document-box-remove::before {
+  content: "\FEC9";
+}
+.mdi-file-document-box-remove-outline::before {
+  content: "\FECA";
+}
+.mdi-file-document-box-search::before {
+  content: "\FECB";
+}
+.mdi-file-document-box-search-outline::before {
+  content: "\FECC";
+}
+.mdi-file-document-edit::before {
+  content: "\FDA4";
+}
+.mdi-file-document-edit-outline::before {
+  content: "\FDA5";
+}
+.mdi-file-document-outline::before {
+  content: "\F9ED";
+}
+.mdi-file-download::before {
+  content: "\F964";
+}
+.mdi-file-download-outline::before {
+  content: "\F965";
+}
+.mdi-file-edit::before {
+  content: "\F0212";
+}
+.mdi-file-edit-outline::before {
+  content: "\F0213";
+}
+.mdi-file-excel::before {
+  content: "\F21B";
+}
+.mdi-file-excel-box::before {
+  content: "\F21C";
+}
+.mdi-file-excel-box-outline::before {
+  content: "\F004E";
+}
+.mdi-file-excel-outline::before {
+  content: "\F004F";
+}
+.mdi-file-export::before {
+  content: "\F21D";
+}
+.mdi-file-export-outline::before {
+  content: "\F0050";
+}
+.mdi-file-eye::before {
+  content: "\FDA6";
+}
+.mdi-file-eye-outline::before {
+  content: "\FDA7";
+}
+.mdi-file-find::before {
+  content: "\F21E";
+}
+.mdi-file-find-outline::before {
+  content: "\FB73";
+}
+.mdi-file-hidden::before {
+  content: "\F613";
+}
+.mdi-file-image::before {
+  content: "\F21F";
+}
+.mdi-file-image-outline::before {
+  content: "\FECD";
+}
+.mdi-file-import::before {
+  content: "\F220";
+}
+.mdi-file-import-outline::before {
+  content: "\F0051";
+}
+.mdi-file-key::before {
+  content: "\F01AF";
+}
+.mdi-file-key-outline::before {
+  content: "\F01B0";
+}
+.mdi-file-link::before {
+  content: "\F01A2";
+}
+.mdi-file-link-outline::before {
+  content: "\F01A3";
+}
+.mdi-file-lock::before {
+  content: "\F221";
+}
+.mdi-file-lock-outline::before {
+  content: "\F0052";
+}
+.mdi-file-move::before {
+  content: "\FAB8";
+}
+.mdi-file-move-outline::before {
+  content: "\F0053";
+}
+.mdi-file-multiple::before {
+  content: "\F222";
+}
+.mdi-file-multiple-outline::before {
+  content: "\F0054";
+}
+.mdi-file-music::before {
+  content: "\F223";
+}
+.mdi-file-music-outline::before {
+  content: "\FE7C";
+}
+.mdi-file-outline::before {
+  content: "\F224";
+}
+.mdi-file-pdf::before {
+  content: "\F225";
+}
+.mdi-file-pdf-box::before {
+  content: "\F226";
+}
+.mdi-file-pdf-box-outline::before {
+  content: "\FFD3";
+}
+.mdi-file-pdf-outline::before {
+  content: "\FE7D";
+}
+.mdi-file-percent::before {
+  content: "\F81D";
+}
+.mdi-file-percent-outline::before {
+  content: "\F0055";
+}
+.mdi-file-phone::before {
+  content: "\F01A4";
+}
+.mdi-file-phone-outline::before {
+  content: "\F01A5";
+}
+.mdi-file-plus::before {
+  content: "\F751";
+}
+.mdi-file-plus-outline::before {
+  content: "\FF0A";
+}
+.mdi-file-powerpoint::before {
+  content: "\F227";
+}
+.mdi-file-powerpoint-box::before {
+  content: "\F228";
+}
+.mdi-file-powerpoint-box-outline::before {
+  content: "\F0056";
+}
+.mdi-file-powerpoint-outline::before {
+  content: "\F0057";
+}
+.mdi-file-presentation-box::before {
+  content: "\F229";
+}
+.mdi-file-question::before {
+  content: "\F86E";
+}
+.mdi-file-question-outline::before {
+  content: "\F0058";
+}
+.mdi-file-remove::before {
+  content: "\FB74";
+}
+.mdi-file-remove-outline::before {
+  content: "\F0059";
+}
+.mdi-file-replace::before {
+  content: "\FB17";
+}
+.mdi-file-replace-outline::before {
+  content: "\FB18";
+}
+.mdi-file-restore::before {
+  content: "\F670";
+}
+.mdi-file-restore-outline::before {
+  content: "\F005A";
+}
+.mdi-file-search::before {
+  content: "\FC58";
+}
+.mdi-file-search-outline::before {
+  content: "\FC59";
+}
+.mdi-file-send::before {
+  content: "\F22A";
+}
+.mdi-file-send-outline::before {
+  content: "\F005B";
+}
+.mdi-file-settings::before {
+  content: "\F00A4";
+}
+.mdi-file-settings-outline::before {
+  content: "\F00A5";
+}
+.mdi-file-settings-variant::before {
+  content: "\F00A6";
+}
+.mdi-file-settings-variant-outline::before {
+  content: "\F00A7";
+}
+.mdi-file-star::before {
+  content: "\F005C";
+}
+.mdi-file-star-outline::before {
+  content: "\F005D";
+}
+.mdi-file-swap::before {
+  content: "\FFD4";
+}
+.mdi-file-swap-outline::before {
+  content: "\FFD5";
+}
+.mdi-file-sync::before {
+  content: "\F0241";
+}
+.mdi-file-sync-outline::before {
+  content: "\F0242";
+}
+.mdi-file-table::before {
+  content: "\FC5A";
+}
+.mdi-file-table-box::before {
+  content: "\F010C";
+}
+.mdi-file-table-box-multiple::before {
+  content: "\F010D";
+}
+.mdi-file-table-box-multiple-outline::before {
+  content: "\F010E";
+}
+.mdi-file-table-box-outline::before {
+  content: "\F010F";
+}
+.mdi-file-table-outline::before {
+  content: "\FC5B";
+}
+.mdi-file-tree::before {
+  content: "\F645";
+}
+.mdi-file-undo::before {
+  content: "\F8DB";
+}
+.mdi-file-undo-outline::before {
+  content: "\F005E";
+}
+.mdi-file-upload::before {
+  content: "\FA4C";
+}
+.mdi-file-upload-outline::before {
+  content: "\FA4D";
+}
+.mdi-file-video::before {
+  content: "\F22B";
+}
+.mdi-file-video-outline::before {
+  content: "\FE10";
+}
+.mdi-file-word::before {
+  content: "\F22C";
+}
+.mdi-file-word-box::before {
+  content: "\F22D";
+}
+.mdi-file-word-box-outline::before {
+  content: "\F005F";
+}
+.mdi-file-word-outline::before {
+  content: "\F0060";
+}
+.mdi-film::before {
+  content: "\F22F";
+}
+.mdi-filmstrip::before {
+  content: "\F230";
+}
+.mdi-filmstrip-off::before {
+  content: "\F231";
+}
+.mdi-filter::before {
+  content: "\F232";
+}
+.mdi-filter-menu::before {
+  content: "\F0110";
+}
+.mdi-filter-menu-outline::before {
+  content: "\F0111";
+}
+.mdi-filter-minus::before {
+  content: "\FF0B";
+}
+.mdi-filter-minus-outline::before {
+  content: "\FF0C";
+}
+.mdi-filter-outline::before {
+  content: "\F233";
+}
+.mdi-filter-plus::before {
+  content: "\FF0D";
+}
+.mdi-filter-plus-outline::before {
+  content: "\FF0E";
+}
+.mdi-filter-remove::before {
+  content: "\F234";
+}
+.mdi-filter-remove-outline::before {
+  content: "\F235";
+}
+.mdi-filter-variant::before {
+  content: "\F236";
+}
+.mdi-filter-variant-minus::before {
+  content: "\F013D";
+}
+.mdi-filter-variant-plus::before {
+  content: "\F013E";
+}
+.mdi-filter-variant-remove::before {
+  content: "\F0061";
+}
+.mdi-finance::before {
+  content: "\F81E";
+}
+.mdi-find-replace::before {
+  content: "\F6D3";
+}
+.mdi-fingerprint::before {
+  content: "\F237";
+}
+.mdi-fingerprint-off::before {
+  content: "\FECE";
+}
+.mdi-fire::before {
+  content: "\F238";
+}
+.mdi-fire-extinguisher::before {
+  content: "\FF0F";
+}
+.mdi-fire-hydrant::before {
+  content: "\F0162";
+}
+.mdi-fire-hydrant-alert::before {
+  content: "\F0163";
+}
+.mdi-fire-hydrant-off::before {
+  content: "\F0164";
+}
+.mdi-fire-truck::before {
+  content: "\F8AA";
+}
+.mdi-firebase::before {
+  content: "\F966";
+}
+.mdi-firefox::before {
+  content: "\F239";
+}
+.mdi-fireplace::before {
+  content: "\FE11";
+}
+.mdi-fireplace-off::before {
+  content: "\FE12";
+}
+.mdi-firework::before {
+  content: "\FE13";
+}
+.mdi-fish::before {
+  content: "\F23A";
+}
+.mdi-fishbowl::before {
+  content: "\FF10";
+}
+.mdi-fishbowl-outline::before {
+  content: "\FF11";
+}
+.mdi-fit-to-page::before {
+  content: "\FF12";
+}
+.mdi-fit-to-page-outline::before {
+  content: "\FF13";
+}
+.mdi-flag::before {
+  content: "\F23B";
+}
+.mdi-flag-checkered::before {
+  content: "\F23C";
+}
+.mdi-flag-minus::before {
+  content: "\FB75";
+}
+.mdi-flag-minus-outline::before {
+  content: "\F00DD";
+}
+.mdi-flag-outline::before {
+  content: "\F23D";
+}
+.mdi-flag-plus::before {
+  content: "\FB76";
+}
+.mdi-flag-plus-outline::before {
+  content: "\F00DE";
+}
+.mdi-flag-remove::before {
+  content: "\FB77";
+}
+.mdi-flag-remove-outline::before {
+  content: "\F00DF";
+}
+.mdi-flag-triangle::before {
+  content: "\F23F";
+}
+.mdi-flag-variant::before {
+  content: "\F240";
+}
+.mdi-flag-variant-outline::before {
+  content: "\F23E";
+}
+.mdi-flare::before {
+  content: "\FD4E";
+}
+.mdi-flash::before {
+  content: "\F241";
+}
+.mdi-flash-alert::before {
+  content: "\FF14";
+}
+.mdi-flash-alert-outline::before {
+  content: "\FF15";
+}
+.mdi-flash-auto::before {
+  content: "\F242";
+}
+.mdi-flash-circle::before {
+  content: "\F81F";
+}
+.mdi-flash-off::before {
+  content: "\F243";
+}
+.mdi-flash-outline::before {
+  content: "\F6D4";
+}
+.mdi-flash-red-eye::before {
+  content: "\F67A";
+}
+.mdi-flashlight::before {
+  content: "\F244";
+}
+.mdi-flashlight-off::before {
+  content: "\F245";
+}
+.mdi-flask::before {
+  content: "\F093";
+}
+.mdi-flask-empty::before {
+  content: "\F094";
+}
+.mdi-flask-empty-minus::before {
+  content: "\F0265";
+}
+.mdi-flask-empty-minus-outline::before {
+  content: "\F0266";
+}
+.mdi-flask-empty-outline::before {
+  content: "\F095";
+}
+.mdi-flask-empty-plus::before {
+  content: "\F0267";
+}
+.mdi-flask-empty-plus-outline::before {
+  content: "\F0268";
+}
+.mdi-flask-empty-remove::before {
+  content: "\F0269";
+}
+.mdi-flask-empty-remove-outline::before {
+  content: "\F026A";
+}
+.mdi-flask-minus::before {
+  content: "\F026B";
+}
+.mdi-flask-minus-outline::before {
+  content: "\F026C";
+}
+.mdi-flask-outline::before {
+  content: "\F096";
+}
+.mdi-flask-plus::before {
+  content: "\F026D";
+}
+.mdi-flask-plus-outline::before {
+  content: "\F026E";
+}
+.mdi-flask-remove::before {
+  content: "\F026F";
+}
+.mdi-flask-remove-outline::before {
+  content: "\F0270";
+}
+.mdi-flask-round-bottom::before {
+  content: "\F0276";
+}
+.mdi-flask-round-bottom-empty::before {
+  content: "\F0277";
+}
+.mdi-flask-round-bottom-empty-outline::before {
+  content: "\F0278";
+}
+.mdi-flask-round-bottom-outline::before {
+  content: "\F0279";
+}
+.mdi-flattr::before {
+  content: "\F246";
+}
+.mdi-fleur-de-lis::before {
+  content: "\F032E";
+}
+.mdi-flickr::before {
+  content: "\FCE3";
+}
+.mdi-flip-horizontal::before {
+  content: "\F0112";
+}
+.mdi-flip-to-back::before {
+  content: "\F247";
+}
+.mdi-flip-to-front::before {
+  content: "\F248";
+}
+.mdi-flip-vertical::before {
+  content: "\F0113";
+}
+.mdi-floor-lamp::before {
+  content: "\F8DC";
+}
+.mdi-floor-lamp-dual::before {
+  content: "\F0062";
+}
+.mdi-floor-lamp-variant::before {
+  content: "\F0063";
+}
+.mdi-floor-plan::before {
+  content: "\F820";
+}
+.mdi-floppy::before {
+  content: "\F249";
+}
+.mdi-floppy-variant::before {
+  content: "\F9EE";
+}
+.mdi-flower::before {
+  content: "\F24A";
+}
+.mdi-flower-outline::before {
+  content: "\F9EF";
+}
+.mdi-flower-poppy::before {
+  content: "\FCE4";
+}
+.mdi-flower-tulip::before {
+  content: "\F9F0";
+}
+.mdi-flower-tulip-outline::before {
+  content: "\F9F1";
+}
+.mdi-focus-auto::before {
+  content: "\FF6B";
+}
+.mdi-focus-field::before {
+  content: "\FF6C";
+}
+.mdi-focus-field-horizontal::before {
+  content: "\FF6D";
+}
+.mdi-focus-field-vertical::before {
+  content: "\FF6E";
+}
+.mdi-folder::before {
+  content: "\F24B";
+}
+.mdi-folder-account::before {
+  content: "\F24C";
+}
+.mdi-folder-account-outline::before {
+  content: "\FB78";
+}
+.mdi-folder-alert::before {
+  content: "\FDA8";
+}
+.mdi-folder-alert-outline::before {
+  content: "\FDA9";
+}
+.mdi-folder-clock::before {
+  content: "\FAB9";
+}
+.mdi-folder-clock-outline::before {
+  content: "\FABA";
+}
+.mdi-folder-download::before {
+  content: "\F24D";
+}
+.mdi-folder-download-outline::before {
+  content: "\F0114";
+}
+.mdi-folder-edit::before {
+  content: "\F8DD";
+}
+.mdi-folder-edit-outline::before {
+  content: "\FDAA";
+}
+.mdi-folder-google-drive::before {
+  content: "\F24E";
+}
+.mdi-folder-heart::before {
+  content: "\F0115";
+}
+.mdi-folder-heart-outline::before {
+  content: "\F0116";
+}
+.mdi-folder-home::before {
+  content: "\F00E0";
+}
+.mdi-folder-home-outline::before {
+  content: "\F00E1";
+}
+.mdi-folder-image::before {
+  content: "\F24F";
+}
+.mdi-folder-information::before {
+  content: "\F00E2";
+}
+.mdi-folder-information-outline::before {
+  content: "\F00E3";
+}
+.mdi-folder-key::before {
+  content: "\F8AB";
+}
+.mdi-folder-key-network::before {
+  content: "\F8AC";
+}
+.mdi-folder-key-network-outline::before {
+  content: "\FC5C";
+}
+.mdi-folder-key-outline::before {
+  content: "\F0117";
+}
+.mdi-folder-lock::before {
+  content: "\F250";
+}
+.mdi-folder-lock-open::before {
+  content: "\F251";
+}
+.mdi-folder-marker::before {
+  content: "\F0298";
+}
+.mdi-folder-marker-outline::before {
+  content: "\F0299";
+}
+.mdi-folder-move::before {
+  content: "\F252";
+}
+.mdi-folder-move-outline::before {
+  content: "\F0271";
+}
+.mdi-folder-multiple::before {
+  content: "\F253";
+}
+.mdi-folder-multiple-image::before {
+  content: "\F254";
+}
+.mdi-folder-multiple-outline::before {
+  content: "\F255";
+}
+.mdi-folder-music::before {
+  content: "\F0384";
+}
+.mdi-folder-music-outline::before {
+  content: "\F0385";
+}
+.mdi-folder-network::before {
+  content: "\F86F";
+}
+.mdi-folder-network-outline::before {
+  content: "\FC5D";
+}
+.mdi-folder-open::before {
+  content: "\F76F";
+}
+.mdi-folder-open-outline::before {
+  content: "\FDAB";
+}
+.mdi-folder-outline::before {
+  content: "\F256";
+}
+.mdi-folder-plus::before {
+  content: "\F257";
+}
+.mdi-folder-plus-outline::before {
+  content: "\FB79";
+}
+.mdi-folder-pound::before {
+  content: "\FCE5";
+}
+.mdi-folder-pound-outline::before {
+  content: "\FCE6";
+}
+.mdi-folder-remove::before {
+  content: "\F258";
+}
+.mdi-folder-remove-outline::before {
+  content: "\FB7A";
+}
+.mdi-folder-search::before {
+  content: "\F967";
+}
+.mdi-folder-search-outline::before {
+  content: "\F968";
+}
+.mdi-folder-settings::before {
+  content: "\F00A8";
+}
+.mdi-folder-settings-outline::before {
+  content: "\F00A9";
+}
+.mdi-folder-settings-variant::before {
+  content: "\F00AA";
+}
+.mdi-folder-settings-variant-outline::before {
+  content: "\F00AB";
+}
+.mdi-folder-star::before {
+  content: "\F69C";
+}
+.mdi-folder-star-outline::before {
+  content: "\FB7B";
+}
+.mdi-folder-swap::before {
+  content: "\FFD6";
+}
+.mdi-folder-swap-outline::before {
+  content: "\FFD7";
+}
+.mdi-folder-sync::before {
+  content: "\FCE7";
+}
+.mdi-folder-sync-outline::before {
+  content: "\FCE8";
+}
+.mdi-folder-table::before {
+  content: "\F030E";
+}
+.mdi-folder-table-outline::before {
+  content: "\F030F";
+}
+.mdi-folder-text::before {
+  content: "\FC5E";
+}
+.mdi-folder-text-outline::before {
+  content: "\FC5F";
+}
+.mdi-folder-upload::before {
+  content: "\F259";
+}
+.mdi-folder-upload-outline::before {
+  content: "\F0118";
+}
+.mdi-folder-zip::before {
+  content: "\F6EA";
+}
+.mdi-folder-zip-outline::before {
+  content: "\F7B8";
+}
+.mdi-font-awesome::before {
+  content: "\F03A";
+}
+.mdi-food::before {
+  content: "\F25A";
+}
+.mdi-food-apple::before {
+  content: "\F25B";
+}
+.mdi-food-apple-outline::before {
+  content: "\FC60";
+}
+.mdi-food-croissant::before {
+  content: "\F7C7";
+}
+.mdi-food-fork-drink::before {
+  content: "\F5F2";
+}
+.mdi-food-off::before {
+  content: "\F5F3";
+}
+.mdi-food-variant::before {
+  content: "\F25C";
+}
+.mdi-foot-print::before {
+  content: "\FF6F";
+}
+.mdi-football::before {
+  content: "\F25D";
+}
+.mdi-football-australian::before {
+  content: "\F25E";
+}
+.mdi-football-helmet::before {
+  content: "\F25F";
+}
+.mdi-forklift::before {
+  content: "\F7C8";
+}
+.mdi-format-align-bottom::before {
+  content: "\F752";
+}
+.mdi-format-align-center::before {
+  content: "\F260";
+}
+.mdi-format-align-justify::before {
+  content: "\F261";
+}
+.mdi-format-align-left::before {
+  content: "\F262";
+}
+.mdi-format-align-middle::before {
+  content: "\F753";
+}
+.mdi-format-align-right::before {
+  content: "\F263";
+}
+.mdi-format-align-top::before {
+  content: "\F754";
+}
+.mdi-format-annotation-minus::before {
+  content: "\FABB";
+}
+.mdi-format-annotation-plus::before {
+  content: "\F646";
+}
+.mdi-format-bold::before {
+  content: "\F264";
+}
+.mdi-format-clear::before {
+  content: "\F265";
+}
+.mdi-format-color-fill::before {
+  content: "\F266";
+}
+.mdi-format-color-highlight::before {
+  content: "\FE14";
+}
+.mdi-format-color-marker-cancel::before {
+  content: "\F033E";
+}
+.mdi-format-color-text::before {
+  content: "\F69D";
+}
+.mdi-format-columns::before {
+  content: "\F8DE";
+}
+.mdi-format-float-center::before {
+  content: "\F267";
+}
+.mdi-format-float-left::before {
+  content: "\F268";
+}
+.mdi-format-float-none::before {
+  content: "\F269";
+}
+.mdi-format-float-right::before {
+  content: "\F26A";
+}
+.mdi-format-font::before {
+  content: "\F6D5";
+}
+.mdi-format-font-size-decrease::before {
+  content: "\F9F2";
+}
+.mdi-format-font-size-increase::before {
+  content: "\F9F3";
+}
+.mdi-format-header-1::before {
+  content: "\F26B";
+}
+.mdi-format-header-2::before {
+  content: "\F26C";
+}
+.mdi-format-header-3::before {
+  content: "\F26D";
+}
+.mdi-format-header-4::before {
+  content: "\F26E";
+}
+.mdi-format-header-5::before {
+  content: "\F26F";
+}
+.mdi-format-header-6::before {
+  content: "\F270";
+}
+.mdi-format-header-decrease::before {
+  content: "\F271";
+}
+.mdi-format-header-equal::before {
+  content: "\F272";
+}
+.mdi-format-header-increase::before {
+  content: "\F273";
+}
+.mdi-format-header-pound::before {
+  content: "\F274";
+}
+.mdi-format-horizontal-align-center::before {
+  content: "\F61E";
+}
+.mdi-format-horizontal-align-left::before {
+  content: "\F61F";
+}
+.mdi-format-horizontal-align-right::before {
+  content: "\F620";
+}
+.mdi-format-indent-decrease::before {
+  content: "\F275";
+}
+.mdi-format-indent-increase::before {
+  content: "\F276";
+}
+.mdi-format-italic::before {
+  content: "\F277";
+}
+.mdi-format-letter-case::before {
+  content: "\FB19";
+}
+.mdi-format-letter-case-lower::before {
+  content: "\FB1A";
+}
+.mdi-format-letter-case-upper::before {
+  content: "\FB1B";
+}
+.mdi-format-letter-ends-with::before {
+  content: "\FFD8";
+}
+.mdi-format-letter-matches::before {
+  content: "\FFD9";
+}
+.mdi-format-letter-starts-with::before {
+  content: "\FFDA";
+}
+.mdi-format-line-spacing::before {
+  content: "\F278";
+}
+.mdi-format-line-style::before {
+  content: "\F5C8";
+}
+.mdi-format-line-weight::before {
+  content: "\F5C9";
+}
+.mdi-format-list-bulleted::before {
+  content: "\F279";
+}
+.mdi-format-list-bulleted-square::before {
+  content: "\FDAC";
+}
+.mdi-format-list-bulleted-triangle::before {
+  content: "\FECF";
+}
+.mdi-format-list-bulleted-type::before {
+  content: "\F27A";
+}
+.mdi-format-list-checkbox::before {
+  content: "\F969";
+}
+.mdi-format-list-checks::before {
+  content: "\F755";
+}
+.mdi-format-list-numbered::before {
+  content: "\F27B";
+}
+.mdi-format-list-numbered-rtl::before {
+  content: "\FCE9";
+}
+.mdi-format-list-text::before {
+  content: "\F029A";
+}
+.mdi-format-overline::before {
+  content: "\FED0";
+}
+.mdi-format-page-break::before {
+  content: "\F6D6";
+}
+.mdi-format-paint::before {
+  content: "\F27C";
+}
+.mdi-format-paragraph::before {
+  content: "\F27D";
+}
+.mdi-format-pilcrow::before {
+  content: "\F6D7";
+}
+.mdi-format-quote-close::before {
+  content: "\F27E";
+}
+.mdi-format-quote-close-outline::before {
+  content: "\F01D3";
+}
+.mdi-format-quote-open::before {
+  content: "\F756";
+}
+.mdi-format-quote-open-outline::before {
+  content: "\F01D2";
+}
+.mdi-format-rotate-90::before {
+  content: "\F6A9";
+}
+.mdi-format-section::before {
+  content: "\F69E";
+}
+.mdi-format-size::before {
+  content: "\F27F";
+}
+.mdi-format-strikethrough::before {
+  content: "\F280";
+}
+.mdi-format-strikethrough-variant::before {
+  content: "\F281";
+}
+.mdi-format-subscript::before {
+  content: "\F282";
+}
+.mdi-format-superscript::before {
+  content: "\F283";
+}
+.mdi-format-text::before {
+  content: "\F284";
+}
+.mdi-format-text-rotation-angle-down::before {
+  content: "\FFDB";
+}
+.mdi-format-text-rotation-angle-up::before {
+  content: "\FFDC";
+}
+.mdi-format-text-rotation-down::before {
+  content: "\FD4F";
+}
+.mdi-format-text-rotation-down-vertical::before {
+  content: "\FFDD";
+}
+.mdi-format-text-rotation-none::before {
+  content: "\FD50";
+}
+.mdi-format-text-rotation-up::before {
+  content: "\FFDE";
+}
+.mdi-format-text-rotation-vertical::before {
+  content: "\FFDF";
+}
+.mdi-format-text-variant::before {
+  content: "\FE15";
+}
+.mdi-format-text-wrapping-clip::before {
+  content: "\FCEA";
+}
+.mdi-format-text-wrapping-overflow::before {
+  content: "\FCEB";
+}
+.mdi-format-text-wrapping-wrap::before {
+  content: "\FCEC";
+}
+.mdi-format-textbox::before {
+  content: "\FCED";
+}
+.mdi-format-textdirection-l-to-r::before {
+  content: "\F285";
+}
+.mdi-format-textdirection-r-to-l::before {
+  content: "\F286";
+}
+.mdi-format-title::before {
+  content: "\F5F4";
+}
+.mdi-format-underline::before {
+  content: "\F287";
+}
+.mdi-format-vertical-align-bottom::before {
+  content: "\F621";
+}
+.mdi-format-vertical-align-center::before {
+  content: "\F622";
+}
+.mdi-format-vertical-align-top::before {
+  content: "\F623";
+}
+.mdi-format-wrap-inline::before {
+  content: "\F288";
+}
+.mdi-format-wrap-square::before {
+  content: "\F289";
+}
+.mdi-format-wrap-tight::before {
+  content: "\F28A";
+}
+.mdi-format-wrap-top-bottom::before {
+  content: "\F28B";
+}
+.mdi-forum::before {
+  content: "\F28C";
+}
+.mdi-forum-outline::before {
+  content: "\F821";
+}
+.mdi-forward::before {
+  content: "\F28D";
+}
+.mdi-forwardburger::before {
+  content: "\FD51";
+}
+.mdi-fountain::before {
+  content: "\F96A";
+}
+.mdi-fountain-pen::before {
+  content: "\FCEE";
+}
+.mdi-fountain-pen-tip::before {
+  content: "\FCEF";
+}
+.mdi-foursquare::before {
+  content: "\F28E";
+}
+.mdi-freebsd::before {
+  content: "\F8DF";
+}
+.mdi-frequently-asked-questions::before {
+  content: "\FED1";
+}
+.mdi-fridge::before {
+  content: "\F290";
+}
+.mdi-fridge-alert::before {
+  content: "\F01DC";
+}
+.mdi-fridge-alert-outline::before {
+  content: "\F01DD";
+}
+.mdi-fridge-bottom::before {
+  content: "\F292";
+}
+.mdi-fridge-off::before {
+  content: "\F01DA";
+}
+.mdi-fridge-off-outline::before {
+  content: "\F01DB";
+}
+.mdi-fridge-outline::before {
+  content: "\F28F";
+}
+.mdi-fridge-top::before {
+  content: "\F291";
+}
+.mdi-fruit-cherries::before {
+  content: "\F0064";
+}
+.mdi-fruit-citrus::before {
+  content: "\F0065";
+}
+.mdi-fruit-grapes::before {
+  content: "\F0066";
+}
+.mdi-fruit-grapes-outline::before {
+  content: "\F0067";
+}
+.mdi-fruit-pineapple::before {
+  content: "\F0068";
+}
+.mdi-fruit-watermelon::before {
+  content: "\F0069";
+}
+.mdi-fuel::before {
+  content: "\F7C9";
+}
+.mdi-fullscreen::before {
+  content: "\F293";
+}
+.mdi-fullscreen-exit::before {
+  content: "\F294";
+}
+.mdi-function::before {
+  content: "\F295";
+}
+.mdi-function-variant::before {
+  content: "\F870";
+}
+.mdi-furigana-horizontal::before {
+  content: "\F00AC";
+}
+.mdi-furigana-vertical::before {
+  content: "\F00AD";
+}
+.mdi-fuse::before {
+  content: "\FC61";
+}
+.mdi-fuse-blade::before {
+  content: "\FC62";
+}
+.mdi-gamepad::before {
+  content: "\F296";
+}
+.mdi-gamepad-circle::before {
+  content: "\FE16";
+}
+.mdi-gamepad-circle-down::before {
+  content: "\FE17";
+}
+.mdi-gamepad-circle-left::before {
+  content: "\FE18";
+}
+.mdi-gamepad-circle-outline::before {
+  content: "\FE19";
+}
+.mdi-gamepad-circle-right::before {
+  content: "\FE1A";
+}
+.mdi-gamepad-circle-up::before {
+  content: "\FE1B";
+}
+.mdi-gamepad-down::before {
+  content: "\FE1C";
+}
+.mdi-gamepad-left::before {
+  content: "\FE1D";
+}
+.mdi-gamepad-right::before {
+  content: "\FE1E";
+}
+.mdi-gamepad-round::before {
+  content: "\FE1F";
+}
+.mdi-gamepad-round-down::before {
+  content: "\FE7E";
+}
+.mdi-gamepad-round-left::before {
+  content: "\FE7F";
+}
+.mdi-gamepad-round-outline::before {
+  content: "\FE80";
+}
+.mdi-gamepad-round-right::before {
+  content: "\FE81";
+}
+.mdi-gamepad-round-up::before {
+  content: "\FE82";
+}
+.mdi-gamepad-square::before {
+  content: "\FED2";
+}
+.mdi-gamepad-square-outline::before {
+  content: "\FED3";
+}
+.mdi-gamepad-up::before {
+  content: "\FE83";
+}
+.mdi-gamepad-variant::before {
+  content: "\F297";
+}
+.mdi-gamepad-variant-outline::before {
+  content: "\FED4";
+}
+.mdi-gamma::before {
+  content: "\F0119";
+}
+.mdi-gantry-crane::before {
+  content: "\FDAD";
+}
+.mdi-garage::before {
+  content: "\F6D8";
+}
+.mdi-garage-alert::before {
+  content: "\F871";
+}
+.mdi-garage-alert-variant::before {
+  content: "\F0300";
+}
+.mdi-garage-open::before {
+  content: "\F6D9";
+}
+.mdi-garage-open-variant::before {
+  content: "\F02FF";
+}
+.mdi-garage-variant::before {
+  content: "\F02FE";
+}
+.mdi-gas-cylinder::before {
+  content: "\F647";
+}
+.mdi-gas-station::before {
+  content: "\F298";
+}
+.mdi-gas-station-outline::before {
+  content: "\FED5";
+}
+.mdi-gate::before {
+  content: "\F299";
+}
+.mdi-gate-and::before {
+  content: "\F8E0";
+}
+.mdi-gate-arrow-right::before {
+  content: "\F0194";
+}
+.mdi-gate-nand::before {
+  content: "\F8E1";
+}
+.mdi-gate-nor::before {
+  content: "\F8E2";
+}
+.mdi-gate-not::before {
+  content: "\F8E3";
+}
+.mdi-gate-open::before {
+  content: "\F0195";
+}
+.mdi-gate-or::before {
+  content: "\F8E4";
+}
+.mdi-gate-xnor::before {
+  content: "\F8E5";
+}
+.mdi-gate-xor::before {
+  content: "\F8E6";
+}
+.mdi-gatsby::before {
+  content: "\FE84";
+}
+.mdi-gauge::before {
+  content: "\F29A";
+}
+.mdi-gauge-empty::before {
+  content: "\F872";
+}
+.mdi-gauge-full::before {
+  content: "\F873";
+}
+.mdi-gauge-low::before {
+  content: "\F874";
+}
+.mdi-gavel::before {
+  content: "\F29B";
+}
+.mdi-gender-female::before {
+  content: "\F29C";
+}
+.mdi-gender-male::before {
+  content: "\F29D";
+}
+.mdi-gender-male-female::before {
+  content: "\F29E";
+}
+.mdi-gender-male-female-variant::before {
+  content: "\F016A";
+}
+.mdi-gender-non-binary::before {
+  content: "\F016B";
+}
+.mdi-gender-transgender::before {
+  content: "\F29F";
+}
+.mdi-gentoo::before {
+  content: "\F8E7";
+}
+.mdi-gesture::before {
+  content: "\F7CA";
+}
+.mdi-gesture-double-tap::before {
+  content: "\F73B";
+}
+.mdi-gesture-pinch::before {
+  content: "\FABC";
+}
+.mdi-gesture-spread::before {
+  content: "\FABD";
+}
+.mdi-gesture-swipe::before {
+  content: "\FD52";
+}
+.mdi-gesture-swipe-down::before {
+  content: "\F73C";
+}
+.mdi-gesture-swipe-horizontal::before {
+  content: "\FABE";
+}
+.mdi-gesture-swipe-left::before {
+  content: "\F73D";
+}
+.mdi-gesture-swipe-right::before {
+  content: "\F73E";
+}
+.mdi-gesture-swipe-up::before {
+  content: "\F73F";
+}
+.mdi-gesture-swipe-vertical::before {
+  content: "\FABF";
+}
+.mdi-gesture-tap::before {
+  content: "\F740";
+}
+.mdi-gesture-tap-box::before {
+  content: "\F02D4";
+}
+.mdi-gesture-tap-button::before {
+  content: "\F02D3";
+}
+.mdi-gesture-tap-hold::before {
+  content: "\FD53";
+}
+.mdi-gesture-two-double-tap::before {
+  content: "\F741";
+}
+.mdi-gesture-two-tap::before {
+  content: "\F742";
+}
+.mdi-ghost::before {
+  content: "\F2A0";
+}
+.mdi-ghost-off::before {
+  content: "\F9F4";
+}
+.mdi-gif::before {
+  content: "\FD54";
+}
+.mdi-gift::before {
+  content: "\FE85";
+}
+.mdi-gift-outline::before {
+  content: "\F2A1";
+}
+.mdi-git::before {
+  content: "\F2A2";
+}
+.mdi-github-box::before {
+  content: "\F2A3";
+}
+.mdi-github-circle::before {
+  content: "\F2A4";
+}
+.mdi-github-face::before {
+  content: "\F6DA";
+}
+.mdi-gitlab::before {
+  content: "\FB7C";
+}
+.mdi-glass-cocktail::before {
+  content: "\F356";
+}
+.mdi-glass-flute::before {
+  content: "\F2A5";
+}
+.mdi-glass-mug::before {
+  content: "\F2A6";
+}
+.mdi-glass-mug-variant::before {
+  content: "\F0141";
+}
+.mdi-glass-pint-outline::before {
+  content: "\F0338";
+}
+.mdi-glass-stange::before {
+  content: "\F2A7";
+}
+.mdi-glass-tulip::before {
+  content: "\F2A8";
+}
+.mdi-glass-wine::before {
+  content: "\F875";
+}
+.mdi-glassdoor::before {
+  content: "\F2A9";
+}
+.mdi-glasses::before {
+  content: "\F2AA";
+}
+.mdi-globe-light::before {
+  content: "\F0302";
+}
+.mdi-globe-model::before {
+  content: "\F8E8";
+}
+.mdi-gmail::before {
+  content: "\F2AB";
+}
+.mdi-gnome::before {
+  content: "\F2AC";
+}
+.mdi-go-kart::before {
+  content: "\FD55";
+}
+.mdi-go-kart-track::before {
+  content: "\FD56";
+}
+.mdi-gog::before {
+  content: "\FB7D";
+}
+.mdi-gold::before {
+  content: "\F027A";
+}
+.mdi-golf::before {
+  content: "\F822";
+}
+.mdi-golf-cart::before {
+  content: "\F01CF";
+}
+.mdi-golf-tee::before {
+  content: "\F00AE";
+}
+.mdi-gondola::before {
+  content: "\F685";
+}
+.mdi-goodreads::before {
+  content: "\FD57";
+}
+.mdi-google::before {
+  content: "\F2AD";
+}
+.mdi-google-adwords::before {
+  content: "\FC63";
+}
+.mdi-google-analytics::before {
+  content: "\F7CB";
+}
+.mdi-google-assistant::before {
+  content: "\F7CC";
+}
+.mdi-google-cardboard::before {
+  content: "\F2AE";
+}
+.mdi-google-chrome::before {
+  content: "\F2AF";
+}
+.mdi-google-circles::before {
+  content: "\F2B0";
+}
+.mdi-google-circles-communities::before {
+  content: "\F2B1";
+}
+.mdi-google-circles-extended::before {
+  content: "\F2B2";
+}
+.mdi-google-circles-group::before {
+  content: "\F2B3";
+}
+.mdi-google-classroom::before {
+  content: "\F2C0";
+}
+.mdi-google-cloud::before {
+  content: "\F0221";
+}
+.mdi-google-controller::before {
+  content: "\F2B4";
+}
+.mdi-google-controller-off::before {
+  content: "\F2B5";
+}
+.mdi-google-downasaur::before {
+  content: "\F038D";
+}
+.mdi-google-drive::before {
+  content: "\F2B6";
+}
+.mdi-google-earth::before {
+  content: "\F2B7";
+}
+.mdi-google-fit::before {
+  content: "\F96B";
+}
+.mdi-google-glass::before {
+  content: "\F2B8";
+}
+.mdi-google-hangouts::before {
+  content: "\F2C9";
+}
+.mdi-google-home::before {
+  content: "\F823";
+}
+.mdi-google-keep::before {
+  content: "\F6DB";
+}
+.mdi-google-lens::before {
+  content: "\F9F5";
+}
+.mdi-google-maps::before {
+  content: "\F5F5";
+}
+.mdi-google-my-business::before {
+  content: "\F006A";
+}
+.mdi-google-nearby::before {
+  content: "\F2B9";
+}
+.mdi-google-pages::before {
+  content: "\F2BA";
+}
+.mdi-google-photos::before {
+  content: "\F6DC";
+}
+.mdi-google-physical-web::before {
+  content: "\F2BB";
+}
+.mdi-google-play::before {
+  content: "\F2BC";
+}
+.mdi-google-plus::before {
+  content: "\F2BD";
+}
+.mdi-google-plus-box::before {
+  content: "\F2BE";
+}
+.mdi-google-podcast::before {
+  content: "\FED6";
+}
+.mdi-google-spreadsheet::before {
+  content: "\F9F6";
+}
+.mdi-google-street-view::before {
+  content: "\FC64";
+}
+.mdi-google-translate::before {
+  content: "\F2BF";
+}
+.mdi-gradient::before {
+  content: "\F69F";
+}
+.mdi-grain::before {
+  content: "\FD58";
+}
+.mdi-graph::before {
+  content: "\F006B";
+}
+.mdi-graph-outline::before {
+  content: "\F006C";
+}
+.mdi-graphql::before {
+  content: "\F876";
+}
+.mdi-grave-stone::before {
+  content: "\FB7E";
+}
+.mdi-grease-pencil::before {
+  content: "\F648";
+}
+.mdi-greater-than::before {
+  content: "\F96C";
+}
+.mdi-greater-than-or-equal::before {
+  content: "\F96D";
+}
+.mdi-grid::before {
+  content: "\F2C1";
+}
+.mdi-grid-large::before {
+  content: "\F757";
+}
+.mdi-grid-off::before {
+  content: "\F2C2";
+}
+.mdi-grill::before {
+  content: "\FE86";
+}
+.mdi-grill-outline::before {
+  content: "\F01B5";
+}
+.mdi-group::before {
+  content: "\F2C3";
+}
+.mdi-guitar-acoustic::before {
+  content: "\F770";
+}
+.mdi-guitar-electric::before {
+  content: "\F2C4";
+}
+.mdi-guitar-pick::before {
+  content: "\F2C5";
+}
+.mdi-guitar-pick-outline::before {
+  content: "\F2C6";
+}
+.mdi-guy-fawkes-mask::before {
+  content: "\F824";
+}
+.mdi-hackernews::before {
+  content: "\F624";
+}
+.mdi-hail::before {
+  content: "\FAC0";
+}
+.mdi-hair-dryer::before {
+  content: "\F011A";
+}
+.mdi-hair-dryer-outline::before {
+  content: "\F011B";
+}
+.mdi-halloween::before {
+  content: "\FB7F";
+}
+.mdi-hamburger::before {
+  content: "\F684";
+}
+.mdi-hammer::before {
+  content: "\F8E9";
+}
+.mdi-hammer-screwdriver::before {
+  content: "\F034D";
+}
+.mdi-hammer-wrench::before {
+  content: "\F034E";
+}
+.mdi-hand::before {
+  content: "\FA4E";
+}
+.mdi-hand-heart::before {
+  content: "\F011C";
+}
+.mdi-hand-left::before {
+  content: "\FE87";
+}
+.mdi-hand-okay::before {
+  content: "\FA4F";
+}
+.mdi-hand-peace::before {
+  content: "\FA50";
+}
+.mdi-hand-peace-variant::before {
+  content: "\FA51";
+}
+.mdi-hand-pointing-down::before {
+  content: "\FA52";
+}
+.mdi-hand-pointing-left::before {
+  content: "\FA53";
+}
+.mdi-hand-pointing-right::before {
+  content: "\F2C7";
+}
+.mdi-hand-pointing-up::before {
+  content: "\FA54";
+}
+.mdi-hand-right::before {
+  content: "\FE88";
+}
+.mdi-hand-saw::before {
+  content: "\FE89";
+}
+.mdi-handball::before {
+  content: "\FF70";
+}
+.mdi-handcuffs::before {
+  content: "\F0169";
+}
+.mdi-handshake::before {
+  content: "\F0243";
+}
+.mdi-hanger::before {
+  content: "\F2C8";
+}
+.mdi-hard-hat::before {
+  content: "\F96E";
+}
+.mdi-harddisk::before {
+  content: "\F2CA";
+}
+.mdi-harddisk-plus::before {
+  content: "\F006D";
+}
+.mdi-harddisk-remove::before {
+  content: "\F006E";
+}
+.mdi-hat-fedora::before {
+  content: "\FB80";
+}
+.mdi-hazard-lights::before {
+  content: "\FC65";
+}
+.mdi-hdr::before {
+  content: "\FD59";
+}
+.mdi-hdr-off::before {
+  content: "\FD5A";
+}
+.mdi-head::before {
+  content: "\F0389";
+}
+.mdi-head-alert::before {
+  content: "\F0363";
+}
+.mdi-head-alert-outline::before {
+  content: "\F0364";
+}
+.mdi-head-check::before {
+  content: "\F0365";
+}
+.mdi-head-check-outline::before {
+  content: "\F0366";
+}
+.mdi-head-cog::before {
+  content: "\F0367";
+}
+.mdi-head-cog-outline::before {
+  content: "\F0368";
+}
+.mdi-head-dots-horizontal::before {
+  content: "\F0369";
+}
+.mdi-head-dots-horizontal-outline::before {
+  content: "\F036A";
+}
+.mdi-head-flash::before {
+  content: "\F036B";
+}
+.mdi-head-flash-outline::before {
+  content: "\F036C";
+}
+.mdi-head-heart::before {
+  content: "\F036D";
+}
+.mdi-head-heart-outline::before {
+  content: "\F036E";
+}
+.mdi-head-lightbulb::before {
+  content: "\F036F";
+}
+.mdi-head-lightbulb-outline::before {
+  content: "\F0370";
+}
+.mdi-head-minus::before {
+  content: "\F0371";
+}
+.mdi-head-minus-outline::before {
+  content: "\F0372";
+}
+.mdi-head-outline::before {
+  content: "\F038A";
+}
+.mdi-head-plus::before {
+  content: "\F0373";
+}
+.mdi-head-plus-outline::before {
+  content: "\F0374";
+}
+.mdi-head-question::before {
+  content: "\F0375";
+}
+.mdi-head-question-outline::before {
+  content: "\F0376";
+}
+.mdi-head-remove::before {
+  content: "\F0377";
+}
+.mdi-head-remove-outline::before {
+  content: "\F0378";
+}
+.mdi-head-snowflake::before {
+  content: "\F0379";
+}
+.mdi-head-snowflake-outline::before {
+  content: "\F037A";
+}
+.mdi-head-sync::before {
+  content: "\F037B";
+}
+.mdi-head-sync-outline::before {
+  content: "\F037C";
+}
+.mdi-headphones::before {
+  content: "\F2CB";
+}
+.mdi-headphones-bluetooth::before {
+  content: "\F96F";
+}
+.mdi-headphones-box::before {
+  content: "\F2CC";
+}
+.mdi-headphones-off::before {
+  content: "\F7CD";
+}
+.mdi-headphones-settings::before {
+  content: "\F2CD";
+}
+.mdi-headset::before {
+  content: "\F2CE";
+}
+.mdi-headset-dock::before {
+  content: "\F2CF";
+}
+.mdi-headset-off::before {
+  content: "\F2D0";
+}
+.mdi-heart::before {
+  content: "\F2D1";
+}
+.mdi-heart-box::before {
+  content: "\F2D2";
+}
+.mdi-heart-box-outline::before {
+  content: "\F2D3";
+}
+.mdi-heart-broken::before {
+  content: "\F2D4";
+}
+.mdi-heart-broken-outline::before {
+  content: "\FCF0";
+}
+.mdi-heart-circle::before {
+  content: "\F970";
+}
+.mdi-heart-circle-outline::before {
+  content: "\F971";
+}
+.mdi-heart-flash::before {
+  content: "\FF16";
+}
+.mdi-heart-half::before {
+  content: "\F6DE";
+}
+.mdi-heart-half-full::before {
+  content: "\F6DD";
+}
+.mdi-heart-half-outline::before {
+  content: "\F6DF";
+}
+.mdi-heart-multiple::before {
+  content: "\FA55";
+}
+.mdi-heart-multiple-outline::before {
+  content: "\FA56";
+}
+.mdi-heart-off::before {
+  content: "\F758";
+}
+.mdi-heart-outline::before {
+  content: "\F2D5";
+}
+.mdi-heart-pulse::before {
+  content: "\F5F6";
+}
+.mdi-helicopter::before {
+  content: "\FAC1";
+}
+.mdi-help::before {
+  content: "\F2D6";
+}
+.mdi-help-box::before {
+  content: "\F78A";
+}
+.mdi-help-circle::before {
+  content: "\F2D7";
+}
+.mdi-help-circle-outline::before {
+  content: "\F625";
+}
+.mdi-help-network::before {
+  content: "\F6F4";
+}
+.mdi-help-network-outline::before {
+  content: "\FC66";
+}
+.mdi-help-rhombus::before {
+  content: "\FB81";
+}
+.mdi-help-rhombus-outline::before {
+  content: "\FB82";
+}
+.mdi-hexadecimal::before {
+  content: "\F02D2";
+}
+.mdi-hexagon::before {
+  content: "\F2D8";
+}
+.mdi-hexagon-multiple::before {
+  content: "\F6E0";
+}
+.mdi-hexagon-multiple-outline::before {
+  content: "\F011D";
+}
+.mdi-hexagon-outline::before {
+  content: "\F2D9";
+}
+.mdi-hexagon-slice-1::before {
+  content: "\FAC2";
+}
+.mdi-hexagon-slice-2::before {
+  content: "\FAC3";
+}
+.mdi-hexagon-slice-3::before {
+  content: "\FAC4";
+}
+.mdi-hexagon-slice-4::before {
+  content: "\FAC5";
+}
+.mdi-hexagon-slice-5::before {
+  content: "\FAC6";
+}
+.mdi-hexagon-slice-6::before {
+  content: "\FAC7";
+}
+.mdi-hexagram::before {
+  content: "\FAC8";
+}
+.mdi-hexagram-outline::before {
+  content: "\FAC9";
+}
+.mdi-high-definition::before {
+  content: "\F7CE";
+}
+.mdi-high-definition-box::before {
+  content: "\F877";
+}
+.mdi-highway::before {
+  content: "\F5F7";
+}
+.mdi-hiking::before {
+  content: "\FD5B";
+}
+.mdi-hinduism::before {
+  content: "\F972";
+}
+.mdi-history::before {
+  content: "\F2DA";
+}
+.mdi-hockey-puck::before {
+  content: "\F878";
+}
+.mdi-hockey-sticks::before {
+  content: "\F879";
+}
+.mdi-hololens::before {
+  content: "\F2DB";
+}
+.mdi-home::before {
+  content: "\F2DC";
+}
+.mdi-home-account::before {
+  content: "\F825";
+}
+.mdi-home-alert::before {
+  content: "\F87A";
+}
+.mdi-home-analytics::before {
+  content: "\FED7";
+}
+.mdi-home-assistant::before {
+  content: "\F7CF";
+}
+.mdi-home-automation::before {
+  content: "\F7D0";
+}
+.mdi-home-circle::before {
+  content: "\F7D1";
+}
+.mdi-home-circle-outline::before {
+  content: "\F006F";
+}
+.mdi-home-city::before {
+  content: "\FCF1";
+}
+.mdi-home-city-outline::before {
+  content: "\FCF2";
+}
+.mdi-home-currency-usd::before {
+  content: "\F8AE";
+}
+.mdi-home-edit::before {
+  content: "\F0184";
+}
+.mdi-home-edit-outline::before {
+  content: "\F0185";
+}
+.mdi-home-export-outline::before {
+  content: "\FFB8";
+}
+.mdi-home-flood::before {
+  content: "\FF17";
+}
+.mdi-home-floor-0::before {
+  content: "\FDAE";
+}
+.mdi-home-floor-1::before {
+  content: "\FD5C";
+}
+.mdi-home-floor-2::before {
+  content: "\FD5D";
+}
+.mdi-home-floor-3::before {
+  content: "\FD5E";
+}
+.mdi-home-floor-a::before {
+  content: "\FD5F";
+}
+.mdi-home-floor-b::before {
+  content: "\FD60";
+}
+.mdi-home-floor-g::before {
+  content: "\FD61";
+}
+.mdi-home-floor-l::before {
+  content: "\FD62";
+}
+.mdi-home-floor-negative-1::before {
+  content: "\FDAF";
+}
+.mdi-home-group::before {
+  content: "\FDB0";
+}
+.mdi-home-heart::before {
+  content: "\F826";
+}
+.mdi-home-import-outline::before {
+  content: "\FFB9";
+}
+.mdi-home-lightbulb::before {
+  content: "\F027C";
+}
+.mdi-home-lightbulb-outline::before {
+  content: "\F027D";
+}
+.mdi-home-lock::before {
+  content: "\F8EA";
+}
+.mdi-home-lock-open::before {
+  content: "\F8EB";
+}
+.mdi-home-map-marker::before {
+  content: "\F5F8";
+}
+.mdi-home-minus::before {
+  content: "\F973";
+}
+.mdi-home-modern::before {
+  content: "\F2DD";
+}
+.mdi-home-outline::before {
+  content: "\F6A0";
+}
+.mdi-home-plus::before {
+  content: "\F974";
+}
+.mdi-home-remove::before {
+  content: "\F0272";
+}
+.mdi-home-roof::before {
+  content: "\F0156";
+}
+.mdi-home-thermometer::before {
+  content: "\FF71";
+}
+.mdi-home-thermometer-outline::before {
+  content: "\FF72";
+}
+.mdi-home-variant::before {
+  content: "\F2DE";
+}
+.mdi-home-variant-outline::before {
+  content: "\FB83";
+}
+.mdi-hook::before {
+  content: "\F6E1";
+}
+.mdi-hook-off::before {
+  content: "\F6E2";
+}
+.mdi-hops::before {
+  content: "\F2DF";
+}
+.mdi-horizontal-rotate-clockwise::before {
+  content: "\F011E";
+}
+.mdi-horizontal-rotate-counterclockwise::before {
+  content: "\F011F";
+}
+.mdi-horseshoe::before {
+  content: "\FA57";
+}
+.mdi-hospital::before {
+  content: "\F0017";
+}
+.mdi-hospital-box::before {
+  content: "\F2E0";
+}
+.mdi-hospital-box-outline::before {
+  content: "\F0018";
+}
+.mdi-hospital-building::before {
+  content: "\F2E1";
+}
+.mdi-hospital-marker::before {
+  content: "\F2E2";
+}
+.mdi-hot-tub::before {
+  content: "\F827";
+}
+.mdi-hotel::before {
+  content: "\F2E3";
+}
+.mdi-houzz::before {
+  content: "\F2E4";
+}
+.mdi-houzz-box::before {
+  content: "\F2E5";
+}
+.mdi-hubspot::before {
+  content: "\FCF3";
+}
+.mdi-hulu::before {
+  content: "\F828";
+}
+.mdi-human::before {
+  content: "\F2E6";
+}
+.mdi-human-child::before {
+  content: "\F2E7";
+}
+.mdi-human-female::before {
+  content: "\F649";
+}
+.mdi-human-female-boy::before {
+  content: "\FA58";
+}
+.mdi-human-female-female::before {
+  content: "\FA59";
+}
+.mdi-human-female-girl::before {
+  content: "\FA5A";
+}
+.mdi-human-greeting::before {
+  content: "\F64A";
+}
+.mdi-human-handsdown::before {
+  content: "\F64B";
+}
+.mdi-human-handsup::before {
+  content: "\F64C";
+}
+.mdi-human-male::before {
+  content: "\F64D";
+}
+.mdi-human-male-boy::before {
+  content: "\FA5B";
+}
+.mdi-human-male-female::before {
+  content: "\F2E8";
+}
+.mdi-human-male-girl::before {
+  content: "\FA5C";
+}
+.mdi-human-male-height::before {
+  content: "\FF18";
+}
+.mdi-human-male-height-variant::before {
+  content: "\FF19";
+}
+.mdi-human-male-male::before {
+  content: "\FA5D";
+}
+.mdi-human-pregnant::before {
+  content: "\F5CF";
+}
+.mdi-humble-bundle::before {
+  content: "\F743";
+}
+.mdi-hvac::before {
+  content: "\F037D";
+}
+.mdi-hydraulic-oil-level::before {
+  content: "\F034F";
+}
+.mdi-hydraulic-oil-temperature::before {
+  content: "\F0350";
+}
+.mdi-hydro-power::before {
+  content: "\F0310";
+}
+.mdi-ice-cream::before {
+  content: "\F829";
+}
+.mdi-ice-pop::before {
+  content: "\FF1A";
+}
+.mdi-id-card::before {
+  content: "\FFE0";
+}
+.mdi-identifier::before {
+  content: "\FF1B";
+}
+.mdi-ideogram-cjk::before {
+  content: "\F035C";
+}
+.mdi-ideogram-cjk-variant::before {
+  content: "\F035D";
+}
+.mdi-iframe::before {
+  content: "\FC67";
+}
+.mdi-iframe-array::before {
+  content: "\F0120";
+}
+.mdi-iframe-array-outline::before {
+  content: "\F0121";
+}
+.mdi-iframe-braces::before {
+  content: "\F0122";
+}
+.mdi-iframe-braces-outline::before {
+  content: "\F0123";
+}
+.mdi-iframe-outline::before {
+  content: "\FC68";
+}
+.mdi-iframe-parentheses::before {
+  content: "\F0124";
+}
+.mdi-iframe-parentheses-outline::before {
+  content: "\F0125";
+}
+.mdi-iframe-variable::before {
+  content: "\F0126";
+}
+.mdi-iframe-variable-outline::before {
+  content: "\F0127";
+}
+.mdi-image::before {
+  content: "\F2E9";
+}
+.mdi-image-album::before {
+  content: "\F2EA";
+}
+.mdi-image-area::before {
+  content: "\F2EB";
+}
+.mdi-image-area-close::before {
+  content: "\F2EC";
+}
+.mdi-image-auto-adjust::before {
+  content: "\FFE1";
+}
+.mdi-image-broken::before {
+  content: "\F2ED";
+}
+.mdi-image-broken-variant::before {
+  content: "\F2EE";
+}
+.mdi-image-edit::before {
+  content: "\F020E";
+}
+.mdi-image-edit-outline::before {
+  content: "\F020F";
+}
+.mdi-image-filter::before {
+  content: "\F2EF";
+}
+.mdi-image-filter-black-white::before {
+  content: "\F2F0";
+}
+.mdi-image-filter-center-focus::before {
+  content: "\F2F1";
+}
+.mdi-image-filter-center-focus-strong::before {
+  content: "\FF1C";
+}
+.mdi-image-filter-center-focus-strong-outline::before {
+  content: "\FF1D";
+}
+.mdi-image-filter-center-focus-weak::before {
+  content: "\F2F2";
+}
+.mdi-image-filter-drama::before {
+  content: "\F2F3";
+}
+.mdi-image-filter-frames::before {
+  content: "\F2F4";
+}
+.mdi-image-filter-hdr::before {
+  content: "\F2F5";
+}
+.mdi-image-filter-none::before {
+  content: "\F2F6";
+}
+.mdi-image-filter-tilt-shift::before {
+  content: "\F2F7";
+}
+.mdi-image-filter-vintage::before {
+  content: "\F2F8";
+}
+.mdi-image-frame::before {
+  content: "\FE8A";
+}
+.mdi-image-move::before {
+  content: "\F9F7";
+}
+.mdi-image-multiple::before {
+  content: "\F2F9";
+}
+.mdi-image-off::before {
+  content: "\F82A";
+}
+.mdi-image-off-outline::before {
+  content: "\F01FC";
+}
+.mdi-image-outline::before {
+  content: "\F975";
+}
+.mdi-image-plus::before {
+  content: "\F87B";
+}
+.mdi-image-search::before {
+  content: "\F976";
+}
+.mdi-image-search-outline::before {
+  content: "\F977";
+}
+.mdi-image-size-select-actual::before {
+  content: "\FC69";
+}
+.mdi-image-size-select-large::before {
+  content: "\FC6A";
+}
+.mdi-image-size-select-small::before {
+  content: "\FC6B";
+}
+.mdi-import::before {
+  content: "\F2FA";
+}
+.mdi-inbox::before {
+  content: "\F686";
+}
+.mdi-inbox-arrow-down::before {
+  content: "\F2FB";
+}
+.mdi-inbox-arrow-down-outline::before {
+  content: "\F029B";
+}
+.mdi-inbox-arrow-up::before {
+  content: "\F3D1";
+}
+.mdi-inbox-arrow-up-outline::before {
+  content: "\F029C";
+}
+.mdi-inbox-full::before {
+  content: "\F029D";
+}
+.mdi-inbox-full-outline::before {
+  content: "\F029E";
+}
+.mdi-inbox-multiple::before {
+  content: "\F8AF";
+}
+.mdi-inbox-multiple-outline::before {
+  content: "\FB84";
+}
+.mdi-inbox-outline::before {
+  content: "\F029F";
+}
+.mdi-incognito::before {
+  content: "\F5F9";
+}
+.mdi-infinity::before {
+  content: "\F6E3";
+}
+.mdi-information::before {
+  content: "\F2FC";
+}
+.mdi-information-outline::before {
+  content: "\F2FD";
+}
+.mdi-information-variant::before {
+  content: "\F64E";
+}
+.mdi-instagram::before {
+  content: "\F2FE";
+}
+.mdi-instapaper::before {
+  content: "\F2FF";
+}
+.mdi-instrument-triangle::before {
+  content: "\F0070";
+}
+.mdi-internet-explorer::before {
+  content: "\F300";
+}
+.mdi-invert-colors::before {
+  content: "\F301";
+}
+.mdi-invert-colors-off::before {
+  content: "\FE8B";
+}
+.mdi-iobroker::before {
+  content: "\F0313";
+}
+.mdi-ip::before {
+  content: "\FA5E";
+}
+.mdi-ip-network::before {
+  content: "\FA5F";
+}
+.mdi-ip-network-outline::before {
+  content: "\FC6C";
+}
+.mdi-ipod::before {
+  content: "\FC6D";
+}
+.mdi-islam::before {
+  content: "\F978";
+}
+.mdi-island::before {
+  content: "\F0071";
+}
+.mdi-itunes::before {
+  content: "\F676";
+}
+.mdi-iv-bag::before {
+  content: "\F00E4";
+}
+.mdi-jabber::before {
+  content: "\FDB1";
+}
+.mdi-jeepney::before {
+  content: "\F302";
+}
+.mdi-jellyfish::before {
+  content: "\FF1E";
+}
+.mdi-jellyfish-outline::before {
+  content: "\FF1F";
+}
+.mdi-jira::before {
+  content: "\F303";
+}
+.mdi-jquery::before {
+  content: "\F87C";
+}
+.mdi-jsfiddle::before {
+  content: "\F304";
+}
+.mdi-json::before {
+  content: "\F626";
+}
+.mdi-judaism::before {
+  content: "\F979";
+}
+.mdi-jump-rope::before {
+  content: "\F032A";
+}
+.mdi-kabaddi::before {
+  content: "\FD63";
+}
+.mdi-karate::before {
+  content: "\F82B";
+}
+.mdi-keg::before {
+  content: "\F305";
+}
+.mdi-kettle::before {
+  content: "\F5FA";
+}
+.mdi-kettle-alert::before {
+  content: "\F0342";
+}
+.mdi-kettle-alert-outline::before {
+  content: "\F0343";
+}
+.mdi-kettle-off::before {
+  content: "\F0346";
+}
+.mdi-kettle-off-outline::before {
+  content: "\F0347";
+}
+.mdi-kettle-outline::before {
+  content: "\FF73";
+}
+.mdi-kettle-steam::before {
+  content: "\F0344";
+}
+.mdi-kettle-steam-outline::before {
+  content: "\F0345";
+}
+.mdi-kettlebell::before {
+  content: "\F032B";
+}
+.mdi-key::before {
+  content: "\F306";
+}
+.mdi-key-arrow-right::before {
+  content: "\F033D";
+}
+.mdi-key-change::before {
+  content: "\F307";
+}
+.mdi-key-link::before {
+  content: "\F01CA";
+}
+.mdi-key-minus::before {
+  content: "\F308";
+}
+.mdi-key-outline::before {
+  content: "\FDB2";
+}
+.mdi-key-plus::before {
+  content: "\F309";
+}
+.mdi-key-remove::before {
+  content: "\F30A";
+}
+.mdi-key-star::before {
+  content: "\F01C9";
+}
+.mdi-key-variant::before {
+  content: "\F30B";
+}
+.mdi-key-wireless::before {
+  content: "\FFE2";
+}
+.mdi-keyboard::before {
+  content: "\F30C";
+}
+.mdi-keyboard-backspace::before {
+  content: "\F30D";
+}
+.mdi-keyboard-caps::before {
+  content: "\F30E";
+}
+.mdi-keyboard-close::before {
+  content: "\F30F";
+}
+.mdi-keyboard-esc::before {
+  content: "\F02E2";
+}
+.mdi-keyboard-f1::before {
+  content: "\F02D6";
+}
+.mdi-keyboard-f10::before {
+  content: "\F02DF";
+}
+.mdi-keyboard-f11::before {
+  content: "\F02E0";
+}
+.mdi-keyboard-f12::before {
+  content: "\F02E1";
+}
+.mdi-keyboard-f2::before {
+  content: "\F02D7";
+}
+.mdi-keyboard-f3::before {
+  content: "\F02D8";
+}
+.mdi-keyboard-f4::before {
+  content: "\F02D9";
+}
+.mdi-keyboard-f5::before {
+  content: "\F02DA";
+}
+.mdi-keyboard-f6::before {
+  content: "\F02DB";
+}
+.mdi-keyboard-f7::before {
+  content: "\F02DC";
+}
+.mdi-keyboard-f8::before {
+  content: "\F02DD";
+}
+.mdi-keyboard-f9::before {
+  content: "\F02DE";
+}
+.mdi-keyboard-off::before {
+  content: "\F310";
+}
+.mdi-keyboard-off-outline::before {
+  content: "\FE8C";
+}
+.mdi-keyboard-outline::before {
+  content: "\F97A";
+}
+.mdi-keyboard-return::before {
+  content: "\F311";
+}
+.mdi-keyboard-settings::before {
+  content: "\F9F8";
+}
+.mdi-keyboard-settings-outline::before {
+  content: "\F9F9";
+}
+.mdi-keyboard-space::before {
+  content: "\F0072";
+}
+.mdi-keyboard-tab::before {
+  content: "\F312";
+}
+.mdi-keyboard-variant::before {
+  content: "\F313";
+}
+.mdi-khanda::before {
+  content: "\F0128";
+}
+.mdi-kickstarter::before {
+  content: "\F744";
+}
+.mdi-klingon::before {
+  content: "\F0386";
+}
+.mdi-knife::before {
+  content: "\F9FA";
+}
+.mdi-knife-military::before {
+  content: "\F9FB";
+}
+.mdi-kodi::before {
+  content: "\F314";
+}
+.mdi-kotlin::before {
+  content: "\F0244";
+}
+.mdi-kubernetes::before {
+  content: "\F0129";
+}
+.mdi-label::before {
+  content: "\F315";
+}
+.mdi-label-multiple::before {
+  content: "\F03A0";
+}
+.mdi-label-multiple-outline::before {
+  content: "\F03A1";
+}
+.mdi-label-off::before {
+  content: "\FACA";
+}
+.mdi-label-off-outline::before {
+  content: "\FACB";
+}
+.mdi-label-outline::before {
+  content: "\F316";
+}
+.mdi-label-percent::before {
+  content: "\F0315";
+}
+.mdi-label-percent-outline::before {
+  content: "\F0316";
+}
+.mdi-label-variant::before {
+  content: "\FACC";
+}
+.mdi-label-variant-outline::before {
+  content: "\FACD";
+}
+.mdi-ladybug::before {
+  content: "\F82C";
+}
+.mdi-lambda::before {
+  content: "\F627";
+}
+.mdi-lamp::before {
+  content: "\F6B4";
+}
+.mdi-lan::before {
+  content: "\F317";
+}
+.mdi-lan-check::before {
+  content: "\F02D5";
+}
+.mdi-lan-connect::before {
+  content: "\F318";
+}
+.mdi-lan-disconnect::before {
+  content: "\F319";
+}
+.mdi-lan-pending::before {
+  content: "\F31A";
+}
+.mdi-language-c::before {
+  content: "\F671";
+}
+.mdi-language-cpp::before {
+  content: "\F672";
+}
+.mdi-language-csharp::before {
+  content: "\F31B";
+}
+.mdi-language-css3::before {
+  content: "\F31C";
+}
+.mdi-language-fortran::before {
+  content: "\F0245";
+}
+.mdi-language-go::before {
+  content: "\F7D2";
+}
+.mdi-language-haskell::before {
+  content: "\FC6E";
+}
+.mdi-language-html5::before {
+  content: "\F31D";
+}
+.mdi-language-java::before {
+  content: "\FB1C";
+}
+.mdi-language-javascript::before {
+  content: "\F31E";
+}
+.mdi-language-lua::before {
+  content: "\F8B0";
+}
+.mdi-language-php::before {
+  content: "\F31F";
+}
+.mdi-language-python::before {
+  content: "\F320";
+}
+.mdi-language-python-text::before {
+  content: "\F321";
+}
+.mdi-language-r::before {
+  content: "\F7D3";
+}
+.mdi-language-ruby-on-rails::before {
+  content: "\FACE";
+}
+.mdi-language-swift::before {
+  content: "\F6E4";
+}
+.mdi-language-typescript::before {
+  content: "\F6E5";
+}
+.mdi-laptop::before {
+  content: "\F322";
+}
+.mdi-laptop-chromebook::before {
+  content: "\F323";
+}
+.mdi-laptop-mac::before {
+  content: "\F324";
+}
+.mdi-laptop-off::before {
+  content: "\F6E6";
+}
+.mdi-laptop-windows::before {
+  content: "\F325";
+}
+.mdi-laravel::before {
+  content: "\FACF";
+}
+.mdi-lasso::before {
+  content: "\FF20";
+}
+.mdi-lastfm::before {
+  content: "\F326";
+}
+.mdi-lastpass::before {
+  content: "\F446";
+}
+.mdi-latitude::before {
+  content: "\FF74";
+}
+.mdi-launch::before {
+  content: "\F327";
+}
+.mdi-lava-lamp::before {
+  content: "\F7D4";
+}
+.mdi-layers::before {
+  content: "\F328";
+}
+.mdi-layers-minus::before {
+  content: "\FE8D";
+}
+.mdi-layers-off::before {
+  content: "\F329";
+}
+.mdi-layers-off-outline::before {
+  content: "\F9FC";
+}
+.mdi-layers-outline::before {
+  content: "\F9FD";
+}
+.mdi-layers-plus::before {
+  content: "\FE30";
+}
+.mdi-layers-remove::before {
+  content: "\FE31";
+}
+.mdi-layers-search::before {
+  content: "\F0231";
+}
+.mdi-layers-search-outline::before {
+  content: "\F0232";
+}
+.mdi-layers-triple::before {
+  content: "\FF75";
+}
+.mdi-layers-triple-outline::before {
+  content: "\FF76";
+}
+.mdi-lead-pencil::before {
+  content: "\F64F";
+}
+.mdi-leaf::before {
+  content: "\F32A";
+}
+.mdi-leaf-maple::before {
+  content: "\FC6F";
+}
+.mdi-leaf-maple-off::before {
+  content: "\F0305";
+}
+.mdi-leaf-off::before {
+  content: "\F0304";
+}
+.mdi-leak::before {
+  content: "\FDB3";
+}
+.mdi-leak-off::before {
+  content: "\FDB4";
+}
+.mdi-led-off::before {
+  content: "\F32B";
+}
+.mdi-led-on::before {
+  content: "\F32C";
+}
+.mdi-led-outline::before {
+  content: "\F32D";
+}
+.mdi-led-strip::before {
+  content: "\F7D5";
+}
+.mdi-led-strip-variant::before {
+  content: "\F0073";
+}
+.mdi-led-variant-off::before {
+  content: "\F32E";
+}
+.mdi-led-variant-on::before {
+  content: "\F32F";
+}
+.mdi-led-variant-outline::before {
+  content: "\F330";
+}
+.mdi-leek::before {
+  content: "\F01A8";
+}
+.mdi-less-than::before {
+  content: "\F97B";
+}
+.mdi-less-than-or-equal::before {
+  content: "\F97C";
+}
+.mdi-library::before {
+  content: "\F331";
+}
+.mdi-library-books::before {
+  content: "\F332";
+}
+.mdi-library-movie::before {
+  content: "\FCF4";
+}
+.mdi-library-music::before {
+  content: "\F333";
+}
+.mdi-library-music-outline::before {
+  content: "\FF21";
+}
+.mdi-library-shelves::before {
+  content: "\FB85";
+}
+.mdi-library-video::before {
+  content: "\FCF5";
+}
+.mdi-license::before {
+  content: "\FFE3";
+}
+.mdi-lifebuoy::before {
+  content: "\F87D";
+}
+.mdi-light-switch::before {
+  content: "\F97D";
+}
+.mdi-lightbulb::before {
+  content: "\F335";
+}
+.mdi-lightbulb-cfl::before {
+  content: "\F0233";
+}
+.mdi-lightbulb-cfl-off::before {
+  content: "\F0234";
+}
+.mdi-lightbulb-cfl-spiral::before {
+  content: "\F02A0";
+}
+.mdi-lightbulb-cfl-spiral-off::before {
+  content: "\F02EE";
+}
+.mdi-lightbulb-group::before {
+  content: "\F027E";
+}
+.mdi-lightbulb-group-off::before {
+  content: "\F02F8";
+}
+.mdi-lightbulb-group-off-outline::before {
+  content: "\F02F9";
+}
+.mdi-lightbulb-group-outline::before {
+  content: "\F027F";
+}
+.mdi-lightbulb-multiple::before {
+  content: "\F0280";
+}
+.mdi-lightbulb-multiple-off::before {
+  content: "\F02FA";
+}
+.mdi-lightbulb-multiple-off-outline::before {
+  content: "\F02FB";
+}
+.mdi-lightbulb-multiple-outline::before {
+  content: "\F0281";
+}
+.mdi-lightbulb-off::before {
+  content: "\FE32";
+}
+.mdi-lightbulb-off-outline::before {
+  content: "\FE33";
+}
+.mdi-lightbulb-on::before {
+  content: "\F6E7";
+}
+.mdi-lightbulb-on-outline::before {
+  content: "\F6E8";
+}
+.mdi-lightbulb-outline::before {
+  content: "\F336";
+}
+.mdi-lighthouse::before {
+  content: "\F9FE";
+}
+.mdi-lighthouse-on::before {
+  content: "\F9FF";
+}
+.mdi-link::before {
+  content: "\F337";
+}
+.mdi-link-box::before {
+  content: "\FCF6";
+}
+.mdi-link-box-outline::before {
+  content: "\FCF7";
+}
+.mdi-link-box-variant::before {
+  content: "\FCF8";
+}
+.mdi-link-box-variant-outline::before {
+  content: "\FCF9";
+}
+.mdi-link-lock::before {
+  content: "\F00E5";
+}
+.mdi-link-off::before {
+  content: "\F338";
+}
+.mdi-link-plus::before {
+  content: "\FC70";
+}
+.mdi-link-variant::before {
+  content: "\F339";
+}
+.mdi-link-variant-minus::before {
+  content: "\F012A";
+}
+.mdi-link-variant-off::before {
+  content: "\F33A";
+}
+.mdi-link-variant-plus::before {
+  content: "\F012B";
+}
+.mdi-link-variant-remove::before {
+  content: "\F012C";
+}
+.mdi-linkedin::before {
+  content: "\F33B";
+}
+.mdi-linkedin-box::before {
+  content: "\F33C";
+}
+.mdi-linux::before {
+  content: "\F33D";
+}
+.mdi-linux-mint::before {
+  content: "\F8EC";
+}
+.mdi-litecoin::before {
+  content: "\FA60";
+}
+.mdi-loading::before {
+  content: "\F771";
+}
+.mdi-location-enter::before {
+  content: "\FFE4";
+}
+.mdi-location-exit::before {
+  content: "\FFE5";
+}
+.mdi-lock::before {
+  content: "\F33E";
+}
+.mdi-lock-alert::before {
+  content: "\F8ED";
+}
+.mdi-lock-clock::before {
+  content: "\F97E";
+}
+.mdi-lock-open::before {
+  content: "\F33F";
+}
+.mdi-lock-open-outline::before {
+  content: "\F340";
+}
+.mdi-lock-open-variant::before {
+  content: "\FFE6";
+}
+.mdi-lock-open-variant-outline::before {
+  content: "\FFE7";
+}
+.mdi-lock-outline::before {
+  content: "\F341";
+}
+.mdi-lock-pattern::before {
+  content: "\F6E9";
+}
+.mdi-lock-plus::before {
+  content: "\F5FB";
+}
+.mdi-lock-question::before {
+  content: "\F8EE";
+}
+.mdi-lock-reset::before {
+  content: "\F772";
+}
+.mdi-lock-smart::before {
+  content: "\F8B1";
+}
+.mdi-locker::before {
+  content: "\F7D6";
+}
+.mdi-locker-multiple::before {
+  content: "\F7D7";
+}
+.mdi-login::before {
+  content: "\F342";
+}
+.mdi-login-variant::before {
+  content: "\F5FC";
+}
+.mdi-logout::before {
+  content: "\F343";
+}
+.mdi-logout-variant::before {
+  content: "\F5FD";
+}
+.mdi-longitude::before {
+  content: "\FF77";
+}
+.mdi-looks::before {
+  content: "\F344";
+}
+.mdi-loupe::before {
+  content: "\F345";
+}
+.mdi-lumx::before {
+  content: "\F346";
+}
+.mdi-lungs::before {
+  content: "\F00AF";
+}
+.mdi-lyft::before {
+  content: "\FB1D";
+}
+.mdi-magnet::before {
+  content: "\F347";
+}
+.mdi-magnet-on::before {
+  content: "\F348";
+}
+.mdi-magnify::before {
+  content: "\F349";
+}
+.mdi-magnify-close::before {
+  content: "\F97F";
+}
+.mdi-magnify-minus::before {
+  content: "\F34A";
+}
+.mdi-magnify-minus-cursor::before {
+  content: "\FA61";
+}
+.mdi-magnify-minus-outline::before {
+  content: "\F6EB";
+}
+.mdi-magnify-plus::before {
+  content: "\F34B";
+}
+.mdi-magnify-plus-cursor::before {
+  content: "\FA62";
+}
+.mdi-magnify-plus-outline::before {
+  content: "\F6EC";
+}
+.mdi-magnify-remove-cursor::before {
+  content: "\F0237";
+}
+.mdi-magnify-remove-outline::before {
+  content: "\F0238";
+}
+.mdi-magnify-scan::before {
+  content: "\F02A1";
+}
+.mdi-mail::before {
+  content: "\FED8";
+}
+.mdi-mail-ru::before {
+  content: "\F34C";
+}
+.mdi-mailbox::before {
+  content: "\F6ED";
+}
+.mdi-mailbox-open::before {
+  content: "\FD64";
+}
+.mdi-mailbox-open-outline::before {
+  content: "\FD65";
+}
+.mdi-mailbox-open-up::before {
+  content: "\FD66";
+}
+.mdi-mailbox-open-up-outline::before {
+  content: "\FD67";
+}
+.mdi-mailbox-outline::before {
+  content: "\FD68";
+}
+.mdi-mailbox-up::before {
+  content: "\FD69";
+}
+.mdi-mailbox-up-outline::before {
+  content: "\FD6A";
+}
+.mdi-map::before {
+  content: "\F34D";
+}
+.mdi-map-check::before {
+  content: "\FED9";
+}
+.mdi-map-check-outline::before {
+  content: "\FEDA";
+}
+.mdi-map-clock::before {
+  content: "\FCFA";
+}
+.mdi-map-clock-outline::before {
+  content: "\FCFB";
+}
+.mdi-map-legend::before {
+  content: "\FA00";
+}
+.mdi-map-marker::before {
+  content: "\F34E";
+}
+.mdi-map-marker-alert::before {
+  content: "\FF22";
+}
+.mdi-map-marker-alert-outline::before {
+  content: "\FF23";
+}
+.mdi-map-marker-check::before {
+  content: "\FC71";
+}
+.mdi-map-marker-check-outline::before {
+  content: "\F0326";
+}
+.mdi-map-marker-circle::before {
+  content: "\F34F";
+}
+.mdi-map-marker-distance::before {
+  content: "\F8EF";
+}
+.mdi-map-marker-down::before {
+  content: "\F012D";
+}
+.mdi-map-marker-left::before {
+  content: "\F0306";
+}
+.mdi-map-marker-left-outline::before {
+  content: "\F0308";
+}
+.mdi-map-marker-minus::before {
+  content: "\F650";
+}
+.mdi-map-marker-minus-outline::before {
+  content: "\F0324";
+}
+.mdi-map-marker-multiple::before {
+  content: "\F350";
+}
+.mdi-map-marker-multiple-outline::before {
+  content: "\F02A2";
+}
+.mdi-map-marker-off::before {
+  content: "\F351";
+}
+.mdi-map-marker-off-outline::before {
+  content: "\F0328";
+}
+.mdi-map-marker-outline::before {
+  content: "\F7D8";
+}
+.mdi-map-marker-path::before {
+  content: "\FCFC";
+}
+.mdi-map-marker-plus::before {
+  content: "\F651";
+}
+.mdi-map-marker-plus-outline::before {
+  content: "\F0323";
+}
+.mdi-map-marker-question::before {
+  content: "\FF24";
+}
+.mdi-map-marker-question-outline::before {
+  content: "\FF25";
+}
+.mdi-map-marker-radius::before {
+  content: "\F352";
+}
+.mdi-map-marker-radius-outline::before {
+  content: "\F0327";
+}
+.mdi-map-marker-remove::before {
+  content: "\FF26";
+}
+.mdi-map-marker-remove-outline::before {
+  content: "\F0325";
+}
+.mdi-map-marker-remove-variant::before {
+  content: "\FF27";
+}
+.mdi-map-marker-right::before {
+  content: "\F0307";
+}
+.mdi-map-marker-right-outline::before {
+  content: "\F0309";
+}
+.mdi-map-marker-up::before {
+  content: "\F012E";
+}
+.mdi-map-minus::before {
+  content: "\F980";
+}
+.mdi-map-outline::before {
+  content: "\F981";
+}
+.mdi-map-plus::before {
+  content: "\F982";
+}
+.mdi-map-search::before {
+  content: "\F983";
+}
+.mdi-map-search-outline::before {
+  content: "\F984";
+}
+.mdi-mapbox::before {
+  content: "\FB86";
+}
+.mdi-margin::before {
+  content: "\F353";
+}
+.mdi-markdown::before {
+  content: "\F354";
+}
+.mdi-markdown-outline::before {
+  content: "\FF78";
+}
+.mdi-marker::before {
+  content: "\F652";
+}
+.mdi-marker-cancel::before {
+  content: "\FDB5";
+}
+.mdi-marker-check::before {
+  content: "\F355";
+}
+.mdi-mastodon::before {
+  content: "\FAD0";
+}
+.mdi-mastodon-variant::before {
+  content: "\FAD1";
+}
+.mdi-material-design::before {
+  content: "\F985";
+}
+.mdi-material-ui::before {
+  content: "\F357";
+}
+.mdi-math-compass::before {
+  content: "\F358";
+}
+.mdi-math-cos::before {
+  content: "\FC72";
+}
+.mdi-math-integral::before {
+  content: "\FFE8";
+}
+.mdi-math-integral-box::before {
+  content: "\FFE9";
+}
+.mdi-math-log::before {
+  content: "\F00B0";
+}
+.mdi-math-norm::before {
+  content: "\FFEA";
+}
+.mdi-math-norm-box::before {
+  content: "\FFEB";
+}
+.mdi-math-sin::before {
+  content: "\FC73";
+}
+.mdi-math-tan::before {
+  content: "\FC74";
+}
+.mdi-matrix::before {
+  content: "\F628";
+}
+.mdi-medal::before {
+  content: "\F986";
+}
+.mdi-medal-outline::before {
+  content: "\F0351";
+}
+.mdi-medical-bag::before {
+  content: "\F6EE";
+}
+.mdi-meditation::before {
+  content: "\F01A6";
+}
+.mdi-medium::before {
+  content: "\F35A";
+}
+.mdi-meetup::before {
+  content: "\FAD2";
+}
+.mdi-memory::before {
+  content: "\F35B";
+}
+.mdi-menu::before {
+  content: "\F35C";
+}
+.mdi-menu-down::before {
+  content: "\F35D";
+}
+.mdi-menu-down-outline::before {
+  content: "\F6B5";
+}
+.mdi-menu-left::before {
+  content: "\F35E";
+}
+.mdi-menu-left-outline::before {
+  content: "\FA01";
+}
+.mdi-menu-open::before {
+  content: "\FB87";
+}
+.mdi-menu-right::before {
+  content: "\F35F";
+}
+.mdi-menu-right-outline::before {
+  content: "\FA02";
+}
+.mdi-menu-swap::before {
+  content: "\FA63";
+}
+.mdi-menu-swap-outline::before {
+  content: "\FA64";
+}
+.mdi-menu-up::before {
+  content: "\F360";
+}
+.mdi-menu-up-outline::before {
+  content: "\F6B6";
+}
+.mdi-merge::before {
+  content: "\FF79";
+}
+.mdi-message::before {
+  content: "\F361";
+}
+.mdi-message-alert::before {
+  content: "\F362";
+}
+.mdi-message-alert-outline::before {
+  content: "\FA03";
+}
+.mdi-message-arrow-left::before {
+  content: "\F031D";
+}
+.mdi-message-arrow-left-outline::before {
+  content: "\F031E";
+}
+.mdi-message-arrow-right::before {
+  content: "\F031F";
+}
+.mdi-message-arrow-right-outline::before {
+  content: "\F0320";
+}
+.mdi-message-bulleted::before {
+  content: "\F6A1";
+}
+.mdi-message-bulleted-off::before {
+  content: "\F6A2";
+}
+.mdi-message-draw::before {
+  content: "\F363";
+}
+.mdi-message-image::before {
+  content: "\F364";
+}
+.mdi-message-image-outline::before {
+  content: "\F0197";
+}
+.mdi-message-lock::before {
+  content: "\FFEC";
+}
+.mdi-message-lock-outline::before {
+  content: "\F0198";
+}
+.mdi-message-minus::before {
+  content: "\F0199";
+}
+.mdi-message-minus-outline::before {
+  content: "\F019A";
+}
+.mdi-message-outline::before {
+  content: "\F365";
+}
+.mdi-message-plus::before {
+  content: "\F653";
+}
+.mdi-message-plus-outline::before {
+  content: "\F00E6";
+}
+.mdi-message-processing::before {
+  content: "\F366";
+}
+.mdi-message-processing-outline::before {
+  content: "\F019B";
+}
+.mdi-message-reply::before {
+  content: "\F367";
+}
+.mdi-message-reply-text::before {
+  content: "\F368";
+}
+.mdi-message-settings::before {
+  content: "\F6EF";
+}
+.mdi-message-settings-outline::before {
+  content: "\F019C";
+}
+.mdi-message-settings-variant::before {
+  content: "\F6F0";
+}
+.mdi-message-settings-variant-outline::before {
+  content: "\F019D";
+}
+.mdi-message-text::before {
+  content: "\F369";
+}
+.mdi-message-text-clock::before {
+  content: "\F019E";
+}
+.mdi-message-text-clock-outline::before {
+  content: "\F019F";
+}
+.mdi-message-text-lock::before {
+  content: "\FFED";
+}
+.mdi-message-text-lock-outline::before {
+  content: "\F01A0";
+}
+.mdi-message-text-outline::before {
+  content: "\F36A";
+}
+.mdi-message-video::before {
+  content: "\F36B";
+}
+.mdi-meteor::before {
+  content: "\F629";
+}
+.mdi-metronome::before {
+  content: "\F7D9";
+}
+.mdi-metronome-tick::before {
+  content: "\F7DA";
+}
+.mdi-micro-sd::before {
+  content: "\F7DB";
+}
+.mdi-microphone::before {
+  content: "\F36C";
+}
+.mdi-microphone-minus::before {
+  content: "\F8B2";
+}
+.mdi-microphone-off::before {
+  content: "\F36D";
+}
+.mdi-microphone-outline::before {
+  content: "\F36E";
+}
+.mdi-microphone-plus::before {
+  content: "\F8B3";
+}
+.mdi-microphone-settings::before {
+  content: "\F36F";
+}
+.mdi-microphone-variant::before {
+  content: "\F370";
+}
+.mdi-microphone-variant-off::before {
+  content: "\F371";
+}
+.mdi-microscope::before {
+  content: "\F654";
+}
+.mdi-microsoft::before {
+  content: "\F372";
+}
+.mdi-microsoft-dynamics::before {
+  content: "\F987";
+}
+.mdi-microwave::before {
+  content: "\FC75";
+}
+.mdi-middleware::before {
+  content: "\FF7A";
+}
+.mdi-middleware-outline::before {
+  content: "\FF7B";
+}
+.mdi-midi::before {
+  content: "\F8F0";
+}
+.mdi-midi-port::before {
+  content: "\F8F1";
+}
+.mdi-mine::before {
+  content: "\FDB6";
+}
+.mdi-minecraft::before {
+  content: "\F373";
+}
+.mdi-mini-sd::before {
+  content: "\FA04";
+}
+.mdi-minidisc::before {
+  content: "\FA05";
+}
+.mdi-minus::before {
+  content: "\F374";
+}
+.mdi-minus-box::before {
+  content: "\F375";
+}
+.mdi-minus-box-multiple::before {
+  content: "\F016C";
+}
+.mdi-minus-box-multiple-outline::before {
+  content: "\F016D";
+}
+.mdi-minus-box-outline::before {
+  content: "\F6F1";
+}
+.mdi-minus-circle::before {
+  content: "\F376";
+}
+.mdi-minus-circle-outline::before {
+  content: "\F377";
+}
+.mdi-minus-network::before {
+  content: "\F378";
+}
+.mdi-minus-network-outline::before {
+  content: "\FC76";
+}
+.mdi-mirror::before {
+  content: "\F0228";
+}
+.mdi-mixcloud::before {
+  content: "\F62A";
+}
+.mdi-mixed-martial-arts::before {
+  content: "\FD6B";
+}
+.mdi-mixed-reality::before {
+  content: "\F87E";
+}
+.mdi-mixer::before {
+  content: "\F7DC";
+}
+.mdi-molecule::before {
+  content: "\FB88";
+}
+.mdi-monitor::before {
+  content: "\F379";
+}
+.mdi-monitor-cellphone::before {
+  content: "\F988";
+}
+.mdi-monitor-cellphone-star::before {
+  content: "\F989";
+}
+.mdi-monitor-clean::before {
+  content: "\F012F";
+}
+.mdi-monitor-dashboard::before {
+  content: "\FA06";
+}
+.mdi-monitor-edit::before {
+  content: "\F02F1";
+}
+.mdi-monitor-lock::before {
+  content: "\FDB7";
+}
+.mdi-monitor-multiple::before {
+  content: "\F37A";
+}
+.mdi-monitor-off::before {
+  content: "\FD6C";
+}
+.mdi-monitor-screenshot::before {
+  content: "\FE34";
+}
+.mdi-monitor-speaker::before {
+  content: "\FF7C";
+}
+.mdi-monitor-speaker-off::before {
+  content: "\FF7D";
+}
+.mdi-monitor-star::before {
+  content: "\FDB8";
+}
+.mdi-moon-first-quarter::before {
+  content: "\FF7E";
+}
+.mdi-moon-full::before {
+  content: "\FF7F";
+}
+.mdi-moon-last-quarter::before {
+  content: "\FF80";
+}
+.mdi-moon-new::before {
+  content: "\FF81";
+}
+.mdi-moon-waning-crescent::before {
+  content: "\FF82";
+}
+.mdi-moon-waning-gibbous::before {
+  content: "\FF83";
+}
+.mdi-moon-waxing-crescent::before {
+  content: "\FF84";
+}
+.mdi-moon-waxing-gibbous::before {
+  content: "\FF85";
+}
+.mdi-moped::before {
+  content: "\F00B1";
+}
+.mdi-more::before {
+  content: "\F37B";
+}
+.mdi-mother-heart::before {
+  content: "\F033F";
+}
+.mdi-mother-nurse::before {
+  content: "\FCFD";
+}
+.mdi-motion-sensor::before {
+  content: "\FD6D";
+}
+.mdi-motorbike::before {
+  content: "\F37C";
+}
+.mdi-mouse::before {
+  content: "\F37D";
+}
+.mdi-mouse-bluetooth::before {
+  content: "\F98A";
+}
+.mdi-mouse-off::before {
+  content: "\F37E";
+}
+.mdi-mouse-variant::before {
+  content: "\F37F";
+}
+.mdi-mouse-variant-off::before {
+  content: "\F380";
+}
+.mdi-move-resize::before {
+  content: "\F655";
+}
+.mdi-move-resize-variant::before {
+  content: "\F656";
+}
+.mdi-movie::before {
+  content: "\F381";
+}
+.mdi-movie-edit::before {
+  content: "\F014D";
+}
+.mdi-movie-edit-outline::before {
+  content: "\F014E";
+}
+.mdi-movie-filter::before {
+  content: "\F014F";
+}
+.mdi-movie-filter-outline::before {
+  content: "\F0150";
+}
+.mdi-movie-open::before {
+  content: "\FFEE";
+}
+.mdi-movie-open-outline::before {
+  content: "\FFEF";
+}
+.mdi-movie-outline::before {
+  content: "\FDB9";
+}
+.mdi-movie-roll::before {
+  content: "\F7DD";
+}
+.mdi-movie-search::before {
+  content: "\F01FD";
+}
+.mdi-movie-search-outline::before {
+  content: "\F01FE";
+}
+.mdi-muffin::before {
+  content: "\F98B";
+}
+.mdi-multiplication::before {
+  content: "\F382";
+}
+.mdi-multiplication-box::before {
+  content: "\F383";
+}
+.mdi-mushroom::before {
+  content: "\F7DE";
+}
+.mdi-mushroom-outline::before {
+  content: "\F7DF";
+}
+.mdi-music::before {
+  content: "\F759";
+}
+.mdi-music-accidental-double-flat::before {
+  content: "\FF86";
+}
+.mdi-music-accidental-double-sharp::before {
+  content: "\FF87";
+}
+.mdi-music-accidental-flat::before {
+  content: "\FF88";
+}
+.mdi-music-accidental-natural::before {
+  content: "\FF89";
+}
+.mdi-music-accidental-sharp::before {
+  content: "\FF8A";
+}
+.mdi-music-box::before {
+  content: "\F384";
+}
+.mdi-music-box-outline::before {
+  content: "\F385";
+}
+.mdi-music-circle::before {
+  content: "\F386";
+}
+.mdi-music-circle-outline::before {
+  content: "\FAD3";
+}
+.mdi-music-clef-alto::before {
+  content: "\FF8B";
+}
+.mdi-music-clef-bass::before {
+  content: "\FF8C";
+}
+.mdi-music-clef-treble::before {
+  content: "\FF8D";
+}
+.mdi-music-note::before {
+  content: "\F387";
+}
+.mdi-music-note-bluetooth::before {
+  content: "\F5FE";
+}
+.mdi-music-note-bluetooth-off::before {
+  content: "\F5FF";
+}
+.mdi-music-note-eighth::before {
+  content: "\F388";
+}
+.mdi-music-note-eighth-dotted::before {
+  content: "\FF8E";
+}
+.mdi-music-note-half::before {
+  content: "\F389";
+}
+.mdi-music-note-half-dotted::before {
+  content: "\FF8F";
+}
+.mdi-music-note-off::before {
+  content: "\F38A";
+}
+.mdi-music-note-off-outline::before {
+  content: "\FF90";
+}
+.mdi-music-note-outline::before {
+  content: "\FF91";
+}
+.mdi-music-note-plus::before {
+  content: "\FDBA";
+}
+.mdi-music-note-quarter::before {
+  content: "\F38B";
+}
+.mdi-music-note-quarter-dotted::before {
+  content: "\FF92";
+}
+.mdi-music-note-sixteenth::before {
+  content: "\F38C";
+}
+.mdi-music-note-sixteenth-dotted::before {
+  content: "\FF93";
+}
+.mdi-music-note-whole::before {
+  content: "\F38D";
+}
+.mdi-music-note-whole-dotted::before {
+  content: "\FF94";
+}
+.mdi-music-off::before {
+  content: "\F75A";
+}
+.mdi-music-rest-eighth::before {
+  content: "\FF95";
+}
+.mdi-music-rest-half::before {
+  content: "\FF96";
+}
+.mdi-music-rest-quarter::before {
+  content: "\FF97";
+}
+.mdi-music-rest-sixteenth::before {
+  content: "\FF98";
+}
+.mdi-music-rest-whole::before {
+  content: "\FF99";
+}
+.mdi-nail::before {
+  content: "\FDBB";
+}
+.mdi-nas::before {
+  content: "\F8F2";
+}
+.mdi-nativescript::before {
+  content: "\F87F";
+}
+.mdi-nature::before {
+  content: "\F38E";
+}
+.mdi-nature-people::before {
+  content: "\F38F";
+}
+.mdi-navigation::before {
+  content: "\F390";
+}
+.mdi-near-me::before {
+  content: "\F5CD";
+}
+.mdi-necklace::before {
+  content: "\FF28";
+}
+.mdi-needle::before {
+  content: "\F391";
+}
+.mdi-netflix::before {
+  content: "\F745";
+}
+.mdi-network::before {
+  content: "\F6F2";
+}
+.mdi-network-off::before {
+  content: "\FC77";
+}
+.mdi-network-off-outline::before {
+  content: "\FC78";
+}
+.mdi-network-outline::before {
+  content: "\FC79";
+}
+.mdi-network-router::before {
+  content: "\F00B2";
+}
+.mdi-network-strength-1::before {
+  content: "\F8F3";
+}
+.mdi-network-strength-1-alert::before {
+  content: "\F8F4";
+}
+.mdi-network-strength-2::before {
+  content: "\F8F5";
+}
+.mdi-network-strength-2-alert::before {
+  content: "\F8F6";
+}
+.mdi-network-strength-3::before {
+  content: "\F8F7";
+}
+.mdi-network-strength-3-alert::before {
+  content: "\F8F8";
+}
+.mdi-network-strength-4::before {
+  content: "\F8F9";
+}
+.mdi-network-strength-4-alert::before {
+  content: "\F8FA";
+}
+.mdi-network-strength-off::before {
+  content: "\F8FB";
+}
+.mdi-network-strength-off-outline::before {
+  content: "\F8FC";
+}
+.mdi-network-strength-outline::before {
+  content: "\F8FD";
+}
+.mdi-new-box::before {
+  content: "\F394";
+}
+.mdi-newspaper::before {
+  content: "\F395";
+}
+.mdi-newspaper-minus::before {
+  content: "\FF29";
+}
+.mdi-newspaper-plus::before {
+  content: "\FF2A";
+}
+.mdi-newspaper-variant::before {
+  content: "\F0023";
+}
+.mdi-newspaper-variant-multiple::before {
+  content: "\F0024";
+}
+.mdi-newspaper-variant-multiple-outline::before {
+  content: "\F0025";
+}
+.mdi-newspaper-variant-outline::before {
+  content: "\F0026";
+}
+.mdi-nfc::before {
+  content: "\F396";
+}
+.mdi-nfc-off::before {
+  content: "\FE35";
+}
+.mdi-nfc-search-variant::before {
+  content: "\FE36";
+}
+.mdi-nfc-tap::before {
+  content: "\F397";
+}
+.mdi-nfc-variant::before {
+  content: "\F398";
+}
+.mdi-nfc-variant-off::before {
+  content: "\FE37";
+}
+.mdi-ninja::before {
+  content: "\F773";
+}
+.mdi-nintendo-switch::before {
+  content: "\F7E0";
+}
+.mdi-nix::before {
+  content: "\F0130";
+}
+.mdi-nodejs::before {
+  content: "\F399";
+}
+.mdi-noodles::before {
+  content: "\F01A9";
+}
+.mdi-not-equal::before {
+  content: "\F98C";
+}
+.mdi-not-equal-variant::before {
+  content: "\F98D";
+}
+.mdi-note::before {
+  content: "\F39A";
+}
+.mdi-note-multiple::before {
+  content: "\F6B7";
+}
+.mdi-note-multiple-outline::before {
+  content: "\F6B8";
+}
+.mdi-note-outline::before {
+  content: "\F39B";
+}
+.mdi-note-plus::before {
+  content: "\F39C";
+}
+.mdi-note-plus-outline::before {
+  content: "\F39D";
+}
+.mdi-note-text::before {
+  content: "\F39E";
+}
+.mdi-note-text-outline::before {
+  content: "\F0202";
+}
+.mdi-notebook::before {
+  content: "\F82D";
+}
+.mdi-notebook-multiple::before {
+  content: "\FE38";
+}
+.mdi-notebook-outline::before {
+  content: "\FEDC";
+}
+.mdi-notification-clear-all::before {
+  content: "\F39F";
+}
+.mdi-npm::before {
+  content: "\F6F6";
+}
+.mdi-npm-variant::before {
+  content: "\F98E";
+}
+.mdi-npm-variant-outline::before {
+  content: "\F98F";
+}
+.mdi-nuke::before {
+  content: "\F6A3";
+}
+.mdi-null::before {
+  content: "\F7E1";
+}
+.mdi-numeric::before {
+  content: "\F3A0";
+}
+.mdi-numeric-0::before {
+  content: "\30";
+}
+.mdi-numeric-0-box::before {
+  content: "\F3A1";
+}
+.mdi-numeric-0-box-multiple::before {
+  content: "\FF2B";
+}
+.mdi-numeric-0-box-multiple-outline::before {
+  content: "\F3A2";
+}
+.mdi-numeric-0-box-outline::before {
+  content: "\F3A3";
+}
+.mdi-numeric-0-circle::before {
+  content: "\FC7A";
+}
+.mdi-numeric-0-circle-outline::before {
+  content: "\FC7B";
+}
+.mdi-numeric-1::before {
+  content: "\31";
+}
+.mdi-numeric-1-box::before {
+  content: "\F3A4";
+}
+.mdi-numeric-1-box-multiple::before {
+  content: "\FF2C";
+}
+.mdi-numeric-1-box-multiple-outline::before {
+  content: "\F3A5";
+}
+.mdi-numeric-1-box-outline::before {
+  content: "\F3A6";
+}
+.mdi-numeric-1-circle::before {
+  content: "\FC7C";
+}
+.mdi-numeric-1-circle-outline::before {
+  content: "\FC7D";
+}
+.mdi-numeric-10::before {
+  content: "\F000A";
+}
+.mdi-numeric-10-box::before {
+  content: "\FF9A";
+}
+.mdi-numeric-10-box-multiple::before {
+  content: "\F000B";
+}
+.mdi-numeric-10-box-multiple-outline::before {
+  content: "\F000C";
+}
+.mdi-numeric-10-box-outline::before {
+  content: "\FF9B";
+}
+.mdi-numeric-10-circle::before {
+  content: "\F000D";
+}
+.mdi-numeric-10-circle-outline::before {
+  content: "\F000E";
+}
+.mdi-numeric-2::before {
+  content: "\32";
+}
+.mdi-numeric-2-box::before {
+  content: "\F3A7";
+}
+.mdi-numeric-2-box-multiple::before {
+  content: "\FF2D";
+}
+.mdi-numeric-2-box-multiple-outline::before {
+  content: "\F3A8";
+}
+.mdi-numeric-2-box-outline::before {
+  content: "\F3A9";
+}
+.mdi-numeric-2-circle::before {
+  content: "\FC7E";
+}
+.mdi-numeric-2-circle-outline::before {
+  content: "\FC7F";
+}
+.mdi-numeric-3::before {
+  content: "\33";
+}
+.mdi-numeric-3-box::before {
+  content: "\F3AA";
+}
+.mdi-numeric-3-box-multiple::before {
+  content: "\FF2E";
+}
+.mdi-numeric-3-box-multiple-outline::before {
+  content: "\F3AB";
+}
+.mdi-numeric-3-box-outline::before {
+  content: "\F3AC";
+}
+.mdi-numeric-3-circle::before {
+  content: "\FC80";
+}
+.mdi-numeric-3-circle-outline::before {
+  content: "\FC81";
+}
+.mdi-numeric-4::before {
+  content: "\34";
+}
+.mdi-numeric-4-box::before {
+  content: "\F3AD";
+}
+.mdi-numeric-4-box-multiple::before {
+  content: "\FF2F";
+}
+.mdi-numeric-4-box-multiple-outline::before {
+  content: "\F3AE";
+}
+.mdi-numeric-4-box-outline::before {
+  content: "\F3AF";
+}
+.mdi-numeric-4-circle::before {
+  content: "\FC82";
+}
+.mdi-numeric-4-circle-outline::before {
+  content: "\FC83";
+}
+.mdi-numeric-5::before {
+  content: "\35";
+}
+.mdi-numeric-5-box::before {
+  content: "\F3B0";
+}
+.mdi-numeric-5-box-multiple::before {
+  content: "\FF30";
+}
+.mdi-numeric-5-box-multiple-outline::before {
+  content: "\F3B1";
+}
+.mdi-numeric-5-box-outline::before {
+  content: "\F3B2";
+}
+.mdi-numeric-5-circle::before {
+  content: "\FC84";
+}
+.mdi-numeric-5-circle-outline::before {
+  content: "\FC85";
+}
+.mdi-numeric-6::before {
+  content: "\36";
+}
+.mdi-numeric-6-box::before {
+  content: "\F3B3";
+}
+.mdi-numeric-6-box-multiple::before {
+  content: "\FF31";
+}
+.mdi-numeric-6-box-multiple-outline::before {
+  content: "\F3B4";
+}
+.mdi-numeric-6-box-outline::before {
+  content: "\F3B5";
+}
+.mdi-numeric-6-circle::before {
+  content: "\FC86";
+}
+.mdi-numeric-6-circle-outline::before {
+  content: "\FC87";
+}
+.mdi-numeric-7::before {
+  content: "\37";
+}
+.mdi-numeric-7-box::before {
+  content: "\F3B6";
+}
+.mdi-numeric-7-box-multiple::before {
+  content: "\FF32";
+}
+.mdi-numeric-7-box-multiple-outline::before {
+  content: "\F3B7";
+}
+.mdi-numeric-7-box-outline::before {
+  content: "\F3B8";
+}
+.mdi-numeric-7-circle::before {
+  content: "\FC88";
+}
+.mdi-numeric-7-circle-outline::before {
+  content: "\FC89";
+}
+.mdi-numeric-8::before {
+  content: "\38";
+}
+.mdi-numeric-8-box::before {
+  content: "\F3B9";
+}
+.mdi-numeric-8-box-multiple::before {
+  content: "\FF33";
+}
+.mdi-numeric-8-box-multiple-outline::before {
+  content: "\F3BA";
+}
+.mdi-numeric-8-box-outline::before {
+  content: "\F3BB";
+}
+.mdi-numeric-8-circle::before {
+  content: "\FC8A";
+}
+.mdi-numeric-8-circle-outline::before {
+  content: "\FC8B";
+}
+.mdi-numeric-9::before {
+  content: "\39";
+}
+.mdi-numeric-9-box::before {
+  content: "\F3BC";
+}
+.mdi-numeric-9-box-multiple::before {
+  content: "\FF34";
+}
+.mdi-numeric-9-box-multiple-outline::before {
+  content: "\F3BD";
+}
+.mdi-numeric-9-box-outline::before {
+  content: "\F3BE";
+}
+.mdi-numeric-9-circle::before {
+  content: "\FC8C";
+}
+.mdi-numeric-9-circle-outline::before {
+  content: "\FC8D";
+}
+.mdi-numeric-9-plus::before {
+  content: "\F000F";
+}
+.mdi-numeric-9-plus-box::before {
+  content: "\F3BF";
+}
+.mdi-numeric-9-plus-box-multiple::before {
+  content: "\FF35";
+}
+.mdi-numeric-9-plus-box-multiple-outline::before {
+  content: "\F3C0";
+}
+.mdi-numeric-9-plus-box-outline::before {
+  content: "\F3C1";
+}
+.mdi-numeric-9-plus-circle::before {
+  content: "\FC8E";
+}
+.mdi-numeric-9-plus-circle-outline::before {
+  content: "\FC8F";
+}
+.mdi-numeric-negative-1::before {
+  content: "\F0074";
+}
+.mdi-nut::before {
+  content: "\F6F7";
+}
+.mdi-nutrition::before {
+  content: "\F3C2";
+}
+.mdi-nuxt::before {
+  content: "\F0131";
+}
+.mdi-oar::before {
+  content: "\F67B";
+}
+.mdi-ocarina::before {
+  content: "\FDBC";
+}
+.mdi-oci::before {
+  content: "\F0314";
+}
+.mdi-ocr::before {
+  content: "\F0165";
+}
+.mdi-octagon::before {
+  content: "\F3C3";
+}
+.mdi-octagon-outline::before {
+  content: "\F3C4";
+}
+.mdi-octagram::before {
+  content: "\F6F8";
+}
+.mdi-octagram-outline::before {
+  content: "\F774";
+}
+.mdi-odnoklassniki::before {
+  content: "\F3C5";
+}
+.mdi-offer::before {
+  content: "\F0246";
+}
+.mdi-office::before {
+  content: "\F3C6";
+}
+.mdi-office-building::before {
+  content: "\F990";
+}
+.mdi-oil::before {
+  content: "\F3C7";
+}
+.mdi-oil-lamp::before {
+  content: "\FF36";
+}
+.mdi-oil-level::before {
+  content: "\F0075";
+}
+.mdi-oil-temperature::before {
+  content: "\F0019";
+}
+.mdi-omega::before {
+  content: "\F3C9";
+}
+.mdi-one-up::before {
+  content: "\FB89";
+}
+.mdi-onedrive::before {
+  content: "\F3CA";
+}
+.mdi-onenote::before {
+  content: "\F746";
+}
+.mdi-onepassword::before {
+  content: "\F880";
+}
+.mdi-opacity::before {
+  content: "\F5CC";
+}
+.mdi-open-in-app::before {
+  content: "\F3CB";
+}
+.mdi-open-in-new::before {
+  content: "\F3CC";
+}
+.mdi-open-source-initiative::before {
+  content: "\FB8A";
+}
+.mdi-openid::before {
+  content: "\F3CD";
+}
+.mdi-opera::before {
+  content: "\F3CE";
+}
+.mdi-orbit::before {
+  content: "\F018";
+}
+.mdi-origin::before {
+  content: "\FB2B";
+}
+.mdi-ornament::before {
+  content: "\F3CF";
+}
+.mdi-ornament-variant::before {
+  content: "\F3D0";
+}
+.mdi-outdoor-lamp::before {
+  content: "\F0076";
+}
+.mdi-outlook::before {
+  content: "\FCFE";
+}
+.mdi-overscan::before {
+  content: "\F0027";
+}
+.mdi-owl::before {
+  content: "\F3D2";
+}
+.mdi-pac-man::before {
+  content: "\FB8B";
+}
+.mdi-package::before {
+  content: "\F3D3";
+}
+.mdi-package-down::before {
+  content: "\F3D4";
+}
+.mdi-package-up::before {
+  content: "\F3D5";
+}
+.mdi-package-variant::before {
+  content: "\F3D6";
+}
+.mdi-package-variant-closed::before {
+  content: "\F3D7";
+}
+.mdi-page-first::before {
+  content: "\F600";
+}
+.mdi-page-last::before {
+  content: "\F601";
+}
+.mdi-page-layout-body::before {
+  content: "\F6F9";
+}
+.mdi-page-layout-footer::before {
+  content: "\F6FA";
+}
+.mdi-page-layout-header::before {
+  content: "\F6FB";
+}
+.mdi-page-layout-header-footer::before {
+  content: "\FF9C";
+}
+.mdi-page-layout-sidebar-left::before {
+  content: "\F6FC";
+}
+.mdi-page-layout-sidebar-right::before {
+  content: "\F6FD";
+}
+.mdi-page-next::before {
+  content: "\FB8C";
+}
+.mdi-page-next-outline::before {
+  content: "\FB8D";
+}
+.mdi-page-previous::before {
+  content: "\FB8E";
+}
+.mdi-page-previous-outline::before {
+  content: "\FB8F";
+}
+.mdi-palette::before {
+  content: "\F3D8";
+}
+.mdi-palette-advanced::before {
+  content: "\F3D9";
+}
+.mdi-palette-outline::before {
+  content: "\FE6C";
+}
+.mdi-palette-swatch::before {
+  content: "\F8B4";
+}
+.mdi-palette-swatch-outline::before {
+  content: "\F0387";
+}
+.mdi-palm-tree::before {
+  content: "\F0077";
+}
+.mdi-pan::before {
+  content: "\FB90";
+}
+.mdi-pan-bottom-left::before {
+  content: "\FB91";
+}
+.mdi-pan-bottom-right::before {
+  content: "\FB92";
+}
+.mdi-pan-down::before {
+  content: "\FB93";
+}
+.mdi-pan-horizontal::before {
+  content: "\FB94";
+}
+.mdi-pan-left::before {
+  content: "\FB95";
+}
+.mdi-pan-right::before {
+  content: "\FB96";
+}
+.mdi-pan-top-left::before {
+  content: "\FB97";
+}
+.mdi-pan-top-right::before {
+  content: "\FB98";
+}
+.mdi-pan-up::before {
+  content: "\FB99";
+}
+.mdi-pan-vertical::before {
+  content: "\FB9A";
+}
+.mdi-panda::before {
+  content: "\F3DA";
+}
+.mdi-pandora::before {
+  content: "\F3DB";
+}
+.mdi-panorama::before {
+  content: "\F3DC";
+}
+.mdi-panorama-fisheye::before {
+  content: "\F3DD";
+}
+.mdi-panorama-horizontal::before {
+  content: "\F3DE";
+}
+.mdi-panorama-vertical::before {
+  content: "\F3DF";
+}
+.mdi-panorama-wide-angle::before {
+  content: "\F3E0";
+}
+.mdi-paper-cut-vertical::before {
+  content: "\F3E1";
+}
+.mdi-paper-roll::before {
+  content: "\F0182";
+}
+.mdi-paper-roll-outline::before {
+  content: "\F0183";
+}
+.mdi-paperclip::before {
+  content: "\F3E2";
+}
+.mdi-parachute::before {
+  content: "\FC90";
+}
+.mdi-parachute-outline::before {
+  content: "\FC91";
+}
+.mdi-parking::before {
+  content: "\F3E3";
+}
+.mdi-party-popper::before {
+  content: "\F0078";
+}
+.mdi-passport::before {
+  content: "\F7E2";
+}
+.mdi-passport-biometric::before {
+  content: "\FDBD";
+}
+.mdi-pasta::before {
+  content: "\F018B";
+}
+.mdi-patio-heater::before {
+  content: "\FF9D";
+}
+.mdi-patreon::before {
+  content: "\F881";
+}
+.mdi-pause::before {
+  content: "\F3E4";
+}
+.mdi-pause-circle::before {
+  content: "\F3E5";
+}
+.mdi-pause-circle-outline::before {
+  content: "\F3E6";
+}
+.mdi-pause-octagon::before {
+  content: "\F3E7";
+}
+.mdi-pause-octagon-outline::before {
+  content: "\F3E8";
+}
+.mdi-paw::before {
+  content: "\F3E9";
+}
+.mdi-paw-off::before {
+  content: "\F657";
+}
+.mdi-paypal::before {
+  content: "\F882";
+}
+.mdi-pdf-box::before {
+  content: "\FE39";
+}
+.mdi-peace::before {
+  content: "\F883";
+}
+.mdi-peanut::before {
+  content: "\F001E";
+}
+.mdi-peanut-off::before {
+  content: "\F001F";
+}
+.mdi-peanut-off-outline::before {
+  content: "\F0021";
+}
+.mdi-peanut-outline::before {
+  content: "\F0020";
+}
+.mdi-pen::before {
+  content: "\F3EA";
+}
+.mdi-pen-lock::before {
+  content: "\FDBE";
+}
+.mdi-pen-minus::before {
+  content: "\FDBF";
+}
+.mdi-pen-off::before {
+  content: "\FDC0";
+}
+.mdi-pen-plus::before {
+  content: "\FDC1";
+}
+.mdi-pen-remove::before {
+  content: "\FDC2";
+}
+.mdi-pencil::before {
+  content: "\F3EB";
+}
+.mdi-pencil-box::before {
+  content: "\F3EC";
+}
+.mdi-pencil-box-multiple::before {
+  content: "\F016F";
+}
+.mdi-pencil-box-multiple-outline::before {
+  content: "\F0170";
+}
+.mdi-pencil-box-outline::before {
+  content: "\F3ED";
+}
+.mdi-pencil-circle::before {
+  content: "\F6FE";
+}
+.mdi-pencil-circle-outline::before {
+  content: "\F775";
+}
+.mdi-pencil-lock::before {
+  content: "\F3EE";
+}
+.mdi-pencil-lock-outline::before {
+  content: "\FDC3";
+}
+.mdi-pencil-minus::before {
+  content: "\FDC4";
+}
+.mdi-pencil-minus-outline::before {
+  content: "\FDC5";
+}
+.mdi-pencil-off::before {
+  content: "\F3EF";
+}
+.mdi-pencil-off-outline::before {
+  content: "\FDC6";
+}
+.mdi-pencil-outline::before {
+  content: "\FC92";
+}
+.mdi-pencil-plus::before {
+  content: "\FDC7";
+}
+.mdi-pencil-plus-outline::before {
+  content: "\FDC8";
+}
+.mdi-pencil-remove::before {
+  content: "\FDC9";
+}
+.mdi-pencil-remove-outline::before {
+  content: "\FDCA";
+}
+.mdi-pencil-ruler::before {
+  content: "\F037E";
+}
+.mdi-penguin::before {
+  content: "\FEDD";
+}
+.mdi-pentagon::before {
+  content: "\F6FF";
+}
+.mdi-pentagon-outline::before {
+  content: "\F700";
+}
+.mdi-percent::before {
+  content: "\F3F0";
+}
+.mdi-percent-outline::before {
+  content: "\F02A3";
+}
+.mdi-periodic-table::before {
+  content: "\F8B5";
+}
+.mdi-periodic-table-co::before {
+  content: "\F0329";
+}
+.mdi-periodic-table-co2::before {
+  content: "\F7E3";
+}
+.mdi-periscope::before {
+  content: "\F747";
+}
+.mdi-perspective-less::before {
+  content: "\FCFF";
+}
+.mdi-perspective-more::before {
+  content: "\FD00";
+}
+.mdi-pharmacy::before {
+  content: "\F3F1";
+}
+.mdi-phone::before {
+  content: "\F3F2";
+}
+.mdi-phone-alert::before {
+  content: "\FF37";
+}
+.mdi-phone-alert-outline::before {
+  content: "\F01B9";
+}
+.mdi-phone-bluetooth::before {
+  content: "\F3F3";
+}
+.mdi-phone-bluetooth-outline::before {
+  content: "\F01BA";
+}
+.mdi-phone-cancel::before {
+  content: "\F00E7";
+}
+.mdi-phone-cancel-outline::before {
+  content: "\F01BB";
+}
+.mdi-phone-check::before {
+  content: "\F01D4";
+}
+.mdi-phone-check-outline::before {
+  content: "\F01D5";
+}
+.mdi-phone-classic::before {
+  content: "\F602";
+}
+.mdi-phone-classic-off::before {
+  content: "\F02A4";
+}
+.mdi-phone-forward::before {
+  content: "\F3F4";
+}
+.mdi-phone-forward-outline::before {
+  content: "\F01BC";
+}
+.mdi-phone-hangup::before {
+  content: "\F3F5";
+}
+.mdi-phone-hangup-outline::before {
+  content: "\F01BD";
+}
+.mdi-phone-in-talk::before {
+  content: "\F3F6";
+}
+.mdi-phone-in-talk-outline::before {
+  content: "\F01AD";
+}
+.mdi-phone-incoming::before {
+  content: "\F3F7";
+}
+.mdi-phone-incoming-outline::before {
+  content: "\F01BE";
+}
+.mdi-phone-lock::before {
+  content: "\F3F8";
+}
+.mdi-phone-lock-outline::before {
+  content: "\F01BF";
+}
+.mdi-phone-log::before {
+  content: "\F3F9";
+}
+.mdi-phone-log-outline::before {
+  content: "\F01C0";
+}
+.mdi-phone-message::before {
+  content: "\F01C1";
+}
+.mdi-phone-message-outline::before {
+  content: "\F01C2";
+}
+.mdi-phone-minus::before {
+  content: "\F658";
+}
+.mdi-phone-minus-outline::before {
+  content: "\F01C3";
+}
+.mdi-phone-missed::before {
+  content: "\F3FA";
+}
+.mdi-phone-missed-outline::before {
+  content: "\F01D0";
+}
+.mdi-phone-off::before {
+  content: "\FDCB";
+}
+.mdi-phone-off-outline::before {
+  content: "\F01D1";
+}
+.mdi-phone-outgoing::before {
+  content: "\F3FB";
+}
+.mdi-phone-outgoing-outline::before {
+  content: "\F01C4";
+}
+.mdi-phone-outline::before {
+  content: "\FDCC";
+}
+.mdi-phone-paused::before {
+  content: "\F3FC";
+}
+.mdi-phone-paused-outline::before {
+  content: "\F01C5";
+}
+.mdi-phone-plus::before {
+  content: "\F659";
+}
+.mdi-phone-plus-outline::before {
+  content: "\F01C6";
+}
+.mdi-phone-return::before {
+  content: "\F82E";
+}
+.mdi-phone-return-outline::before {
+  content: "\F01C7";
+}
+.mdi-phone-ring::before {
+  content: "\F01D6";
+}
+.mdi-phone-ring-outline::before {
+  content: "\F01D7";
+}
+.mdi-phone-rotate-landscape::before {
+  content: "\F884";
+}
+.mdi-phone-rotate-portrait::before {
+  content: "\F885";
+}
+.mdi-phone-settings::before {
+  content: "\F3FD";
+}
+.mdi-phone-settings-outline::before {
+  content: "\F01C8";
+}
+.mdi-phone-voip::before {
+  content: "\F3FE";
+}
+.mdi-pi::before {
+  content: "\F3FF";
+}
+.mdi-pi-box::before {
+  content: "\F400";
+}
+.mdi-pi-hole::before {
+  content: "\FDCD";
+}
+.mdi-piano::before {
+  content: "\F67C";
+}
+.mdi-pickaxe::before {
+  content: "\F8B6";
+}
+.mdi-picture-in-picture-bottom-right::before {
+  content: "\FE3A";
+}
+.mdi-picture-in-picture-bottom-right-outline::before {
+  content: "\FE3B";
+}
+.mdi-picture-in-picture-top-right::before {
+  content: "\FE3C";
+}
+.mdi-picture-in-picture-top-right-outline::before {
+  content: "\FE3D";
+}
+.mdi-pier::before {
+  content: "\F886";
+}
+.mdi-pier-crane::before {
+  content: "\F887";
+}
+.mdi-pig::before {
+  content: "\F401";
+}
+.mdi-pig-variant::before {
+  content: "\F0028";
+}
+.mdi-piggy-bank::before {
+  content: "\F0029";
+}
+.mdi-pill::before {
+  content: "\F402";
+}
+.mdi-pillar::before {
+  content: "\F701";
+}
+.mdi-pin::before {
+  content: "\F403";
+}
+.mdi-pin-off::before {
+  content: "\F404";
+}
+.mdi-pin-off-outline::before {
+  content: "\F92F";
+}
+.mdi-pin-outline::before {
+  content: "\F930";
+}
+.mdi-pine-tree::before {
+  content: "\F405";
+}
+.mdi-pine-tree-box::before {
+  content: "\F406";
+}
+.mdi-pinterest::before {
+  content: "\F407";
+}
+.mdi-pinterest-box::before {
+  content: "\F408";
+}
+.mdi-pinwheel::before {
+  content: "\FAD4";
+}
+.mdi-pinwheel-outline::before {
+  content: "\FAD5";
+}
+.mdi-pipe::before {
+  content: "\F7E4";
+}
+.mdi-pipe-disconnected::before {
+  content: "\F7E5";
+}
+.mdi-pipe-leak::before {
+  content: "\F888";
+}
+.mdi-pipe-wrench::before {
+  content: "\F037F";
+}
+.mdi-pirate::before {
+  content: "\FA07";
+}
+.mdi-pistol::before {
+  content: "\F702";
+}
+.mdi-piston::before {
+  content: "\F889";
+}
+.mdi-pizza::before {
+  content: "\F409";
+}
+.mdi-play::before {
+  content: "\F40A";
+}
+.mdi-play-box::before {
+  content: "\F02A5";
+}
+.mdi-play-box-outline::before {
+  content: "\F40B";
+}
+.mdi-play-circle::before {
+  content: "\F40C";
+}
+.mdi-play-circle-outline::before {
+  content: "\F40D";
+}
+.mdi-play-network::before {
+  content: "\F88A";
+}
+.mdi-play-network-outline::before {
+  content: "\FC93";
+}
+.mdi-play-outline::before {
+  content: "\FF38";
+}
+.mdi-play-pause::before {
+  content: "\F40E";
+}
+.mdi-play-protected-content::before {
+  content: "\F40F";
+}
+.mdi-play-speed::before {
+  content: "\F8FE";
+}
+.mdi-playlist-check::before {
+  content: "\F5C7";
+}
+.mdi-playlist-edit::before {
+  content: "\F8FF";
+}
+.mdi-playlist-minus::before {
+  content: "\F410";
+}
+.mdi-playlist-music::before {
+  content: "\FC94";
+}
+.mdi-playlist-music-outline::before {
+  content: "\FC95";
+}
+.mdi-playlist-play::before {
+  content: "\F411";
+}
+.mdi-playlist-plus::before {
+  content: "\F412";
+}
+.mdi-playlist-remove::before {
+  content: "\F413";
+}
+.mdi-playlist-star::before {
+  content: "\FDCE";
+}
+.mdi-playstation::before {
+  content: "\F414";
+}
+.mdi-plex::before {
+  content: "\F6B9";
+}
+.mdi-plus::before {
+  content: "\F415";
+}
+.mdi-plus-box::before {
+  content: "\F416";
+}
+.mdi-plus-box-multiple::before {
+  content: "\F334";
+}
+.mdi-plus-box-multiple-outline::before {
+  content: "\F016E";
+}
+.mdi-plus-box-outline::before {
+  content: "\F703";
+}
+.mdi-plus-circle::before {
+  content: "\F417";
+}
+.mdi-plus-circle-multiple-outline::before {
+  content: "\F418";
+}
+.mdi-plus-circle-outline::before {
+  content: "\F419";
+}
+.mdi-plus-minus::before {
+  content: "\F991";
+}
+.mdi-plus-minus-box::before {
+  content: "\F992";
+}
+.mdi-plus-network::before {
+  content: "\F41A";
+}
+.mdi-plus-network-outline::before {
+  content: "\FC96";
+}
+.mdi-plus-one::before {
+  content: "\F41B";
+}
+.mdi-plus-outline::before {
+  content: "\F704";
+}
+.mdi-plus-thick::before {
+  content: "\F0217";
+}
+.mdi-pocket::before {
+  content: "\F41C";
+}
+.mdi-podcast::before {
+  content: "\F993";
+}
+.mdi-podium::before {
+  content: "\FD01";
+}
+.mdi-podium-bronze::before {
+  content: "\FD02";
+}
+.mdi-podium-gold::before {
+  content: "\FD03";
+}
+.mdi-podium-silver::before {
+  content: "\FD04";
+}
+.mdi-point-of-sale::before {
+  content: "\FD6E";
+}
+.mdi-pokeball::before {
+  content: "\F41D";
+}
+.mdi-pokemon-go::before {
+  content: "\FA08";
+}
+.mdi-poker-chip::before {
+  content: "\F82F";
+}
+.mdi-polaroid::before {
+  content: "\F41E";
+}
+.mdi-police-badge::before {
+  content: "\F0192";
+}
+.mdi-police-badge-outline::before {
+  content: "\F0193";
+}
+.mdi-poll::before {
+  content: "\F41F";
+}
+.mdi-poll-box::before {
+  content: "\F420";
+}
+.mdi-poll-box-outline::before {
+  content: "\F02A6";
+}
+.mdi-polymer::before {
+  content: "\F421";
+}
+.mdi-pool::before {
+  content: "\F606";
+}
+.mdi-popcorn::before {
+  content: "\F422";
+}
+.mdi-post::before {
+  content: "\F002A";
+}
+.mdi-post-outline::before {
+  content: "\F002B";
+}
+.mdi-postage-stamp::before {
+  content: "\FC97";
+}
+.mdi-pot::before {
+  content: "\F65A";
+}
+.mdi-pot-mix::before {
+  content: "\F65B";
+}
+.mdi-pound::before {
+  content: "\F423";
+}
+.mdi-pound-box::before {
+  content: "\F424";
+}
+.mdi-pound-box-outline::before {
+  content: "\F01AA";
+}
+.mdi-power::before {
+  content: "\F425";
+}
+.mdi-power-cycle::before {
+  content: "\F900";
+}
+.mdi-power-off::before {
+  content: "\F901";
+}
+.mdi-power-on::before {
+  content: "\F902";
+}
+.mdi-power-plug::before {
+  content: "\F6A4";
+}
+.mdi-power-plug-off::before {
+  content: "\F6A5";
+}
+.mdi-power-settings::before {
+  content: "\F426";
+}
+.mdi-power-sleep::before {
+  content: "\F903";
+}
+.mdi-power-socket::before {
+  content: "\F427";
+}
+.mdi-power-socket-au::before {
+  content: "\F904";
+}
+.mdi-power-socket-de::before {
+  content: "\F0132";
+}
+.mdi-power-socket-eu::before {
+  content: "\F7E6";
+}
+.mdi-power-socket-fr::before {
+  content: "\F0133";
+}
+.mdi-power-socket-jp::before {
+  content: "\F0134";
+}
+.mdi-power-socket-uk::before {
+  content: "\F7E7";
+}
+.mdi-power-socket-us::before {
+  content: "\F7E8";
+}
+.mdi-power-standby::before {
+  content: "\F905";
+}
+.mdi-powershell::before {
+  content: "\FA09";
+}
+.mdi-prescription::before {
+  content: "\F705";
+}
+.mdi-presentation::before {
+  content: "\F428";
+}
+.mdi-presentation-play::before {
+  content: "\F429";
+}
+.mdi-printer::before {
+  content: "\F42A";
+}
+.mdi-printer-3d::before {
+  content: "\F42B";
+}
+.mdi-printer-3d-nozzle::before {
+  content: "\FE3E";
+}
+.mdi-printer-3d-nozzle-alert::before {
+  content: "\F01EB";
+}
+.mdi-printer-3d-nozzle-alert-outline::before {
+  content: "\F01EC";
+}
+.mdi-printer-3d-nozzle-outline::before {
+  content: "\FE3F";
+}
+.mdi-printer-alert::before {
+  content: "\F42C";
+}
+.mdi-printer-check::before {
+  content: "\F0171";
+}
+.mdi-printer-off::before {
+  content: "\FE40";
+}
+.mdi-printer-pos::before {
+  content: "\F0079";
+}
+.mdi-printer-settings::before {
+  content: "\F706";
+}
+.mdi-printer-wireless::before {
+  content: "\FA0A";
+}
+.mdi-priority-high::before {
+  content: "\F603";
+}
+.mdi-priority-low::before {
+  content: "\F604";
+}
+.mdi-professional-hexagon::before {
+  content: "\F42D";
+}
+.mdi-progress-alert::before {
+  content: "\FC98";
+}
+.mdi-progress-check::before {
+  content: "\F994";
+}
+.mdi-progress-clock::before {
+  content: "\F995";
+}
+.mdi-progress-close::before {
+  content: "\F0135";
+}
+.mdi-progress-download::before {
+  content: "\F996";
+}
+.mdi-progress-upload::before {
+  content: "\F997";
+}
+.mdi-progress-wrench::before {
+  content: "\FC99";
+}
+.mdi-projector::before {
+  content: "\F42E";
+}
+.mdi-projector-screen::before {
+  content: "\F42F";
+}
+.mdi-propane-tank::before {
+  content: "\F0382";
+}
+.mdi-propane-tank-outline::before {
+  content: "\F0383";
+}
+.mdi-protocol::before {
+  content: "\FFF9";
+}
+.mdi-publish::before {
+  content: "\F6A6";
+}
+.mdi-pulse::before {
+  content: "\F430";
+}
+.mdi-pumpkin::before {
+  content: "\FB9B";
+}
+.mdi-purse::before {
+  content: "\FF39";
+}
+.mdi-purse-outline::before {
+  content: "\FF3A";
+}
+.mdi-puzzle::before {
+  content: "\F431";
+}
+.mdi-puzzle-outline::before {
+  content: "\FA65";
+}
+.mdi-qi::before {
+  content: "\F998";
+}
+.mdi-qqchat::before {
+  content: "\F605";
+}
+.mdi-qrcode::before {
+  content: "\F432";
+}
+.mdi-qrcode-edit::before {
+  content: "\F8B7";
+}
+.mdi-qrcode-minus::before {
+  content: "\F01B7";
+}
+.mdi-qrcode-plus::before {
+  content: "\F01B6";
+}
+.mdi-qrcode-remove::before {
+  content: "\F01B8";
+}
+.mdi-qrcode-scan::before {
+  content: "\F433";
+}
+.mdi-quadcopter::before {
+  content: "\F434";
+}
+.mdi-quality-high::before {
+  content: "\F435";
+}
+.mdi-quality-low::before {
+  content: "\FA0B";
+}
+.mdi-quality-medium::before {
+  content: "\FA0C";
+}
+.mdi-quicktime::before {
+  content: "\F436";
+}
+.mdi-quora::before {
+  content: "\FD05";
+}
+.mdi-rabbit::before {
+  content: "\F906";
+}
+.mdi-racing-helmet::before {
+  content: "\FD6F";
+}
+.mdi-racquetball::before {
+  content: "\FD70";
+}
+.mdi-radar::before {
+  content: "\F437";
+}
+.mdi-radiator::before {
+  content: "\F438";
+}
+.mdi-radiator-disabled::before {
+  content: "\FAD6";
+}
+.mdi-radiator-off::before {
+  content: "\FAD7";
+}
+.mdi-radio::before {
+  content: "\F439";
+}
+.mdi-radio-am::before {
+  content: "\FC9A";
+}
+.mdi-radio-fm::before {
+  content: "\FC9B";
+}
+.mdi-radio-handheld::before {
+  content: "\F43A";
+}
+.mdi-radio-off::before {
+  content: "\F0247";
+}
+.mdi-radio-tower::before {
+  content: "\F43B";
+}
+.mdi-radioactive::before {
+  content: "\F43C";
+}
+.mdi-radioactive-off::before {
+  content: "\FEDE";
+}
+.mdi-radiobox-blank::before {
+  content: "\F43D";
+}
+.mdi-radiobox-marked::before {
+  content: "\F43E";
+}
+.mdi-radius::before {
+  content: "\FC9C";
+}
+.mdi-radius-outline::before {
+  content: "\FC9D";
+}
+.mdi-railroad-light::before {
+  content: "\FF3B";
+}
+.mdi-raspberry-pi::before {
+  content: "\F43F";
+}
+.mdi-ray-end::before {
+  content: "\F440";
+}
+.mdi-ray-end-arrow::before {
+  content: "\F441";
+}
+.mdi-ray-start::before {
+  content: "\F442";
+}
+.mdi-ray-start-arrow::before {
+  content: "\F443";
+}
+.mdi-ray-start-end::before {
+  content: "\F444";
+}
+.mdi-ray-vertex::before {
+  content: "\F445";
+}
+.mdi-react::before {
+  content: "\F707";
+}
+.mdi-read::before {
+  content: "\F447";
+}
+.mdi-receipt::before {
+  content: "\F449";
+}
+.mdi-record::before {
+  content: "\F44A";
+}
+.mdi-record-circle::before {
+  content: "\FEDF";
+}
+.mdi-record-circle-outline::before {
+  content: "\FEE0";
+}
+.mdi-record-player::before {
+  content: "\F999";
+}
+.mdi-record-rec::before {
+  content: "\F44B";
+}
+.mdi-rectangle::before {
+  content: "\FE41";
+}
+.mdi-rectangle-outline::before {
+  content: "\FE42";
+}
+.mdi-recycle::before {
+  content: "\F44C";
+}
+.mdi-reddit::before {
+  content: "\F44D";
+}
+.mdi-redhat::before {
+  content: "\F0146";
+}
+.mdi-redo::before {
+  content: "\F44E";
+}
+.mdi-redo-variant::before {
+  content: "\F44F";
+}
+.mdi-reflect-horizontal::before {
+  content: "\FA0D";
+}
+.mdi-reflect-vertical::before {
+  content: "\FA0E";
+}
+.mdi-refresh::before {
+  content: "\F450";
+}
+.mdi-refresh-circle::before {
+  content: "\F03A2";
+}
+.mdi-regex::before {
+  content: "\F451";
+}
+.mdi-registered-trademark::before {
+  content: "\FA66";
+}
+.mdi-relative-scale::before {
+  content: "\F452";
+}
+.mdi-reload::before {
+  content: "\F453";
+}
+.mdi-reload-alert::before {
+  content: "\F0136";
+}
+.mdi-reminder::before {
+  content: "\F88B";
+}
+.mdi-remote::before {
+  content: "\F454";
+}
+.mdi-remote-desktop::before {
+  content: "\F8B8";
+}
+.mdi-remote-off::before {
+  content: "\FEE1";
+}
+.mdi-remote-tv::before {
+  content: "\FEE2";
+}
+.mdi-remote-tv-off::before {
+  content: "\FEE3";
+}
+.mdi-rename-box::before {
+  content: "\F455";
+}
+.mdi-reorder-horizontal::before {
+  content: "\F687";
+}
+.mdi-reorder-vertical::before {
+  content: "\F688";
+}
+.mdi-repeat::before {
+  content: "\F456";
+}
+.mdi-repeat-off::before {
+  content: "\F457";
+}
+.mdi-repeat-once::before {
+  content: "\F458";
+}
+.mdi-replay::before {
+  content: "\F459";
+}
+.mdi-reply::before {
+  content: "\F45A";
+}
+.mdi-reply-all::before {
+  content: "\F45B";
+}
+.mdi-reply-all-outline::before {
+  content: "\FF3C";
+}
+.mdi-reply-circle::before {
+  content: "\F01D9";
+}
+.mdi-reply-outline::before {
+  content: "\FF3D";
+}
+.mdi-reproduction::before {
+  content: "\F45C";
+}
+.mdi-resistor::before {
+  content: "\FB1F";
+}
+.mdi-resistor-nodes::before {
+  content: "\FB20";
+}
+.mdi-resize::before {
+  content: "\FA67";
+}
+.mdi-resize-bottom-right::before {
+  content: "\F45D";
+}
+.mdi-responsive::before {
+  content: "\F45E";
+}
+.mdi-restart::before {
+  content: "\F708";
+}
+.mdi-restart-alert::before {
+  content: "\F0137";
+}
+.mdi-restart-off::before {
+  content: "\FD71";
+}
+.mdi-restore::before {
+  content: "\F99A";
+}
+.mdi-restore-alert::before {
+  content: "\F0138";
+}
+.mdi-rewind::before {
+  content: "\F45F";
+}
+.mdi-rewind-10::before {
+  content: "\FD06";
+}
+.mdi-rewind-30::before {
+  content: "\FD72";
+}
+.mdi-rewind-5::before {
+  content: "\F0224";
+}
+.mdi-rewind-outline::before {
+  content: "\F709";
+}
+.mdi-rhombus::before {
+  content: "\F70A";
+}
+.mdi-rhombus-medium::before {
+  content: "\FA0F";
+}
+.mdi-rhombus-outline::before {
+  content: "\F70B";
+}
+.mdi-rhombus-split::before {
+  content: "\FA10";
+}
+.mdi-ribbon::before {
+  content: "\F460";
+}
+.mdi-rice::before {
+  content: "\F7E9";
+}
+.mdi-ring::before {
+  content: "\F7EA";
+}
+.mdi-rivet::before {
+  content: "\FE43";
+}
+.mdi-road::before {
+  content: "\F461";
+}
+.mdi-road-variant::before {
+  content: "\F462";
+}
+.mdi-robber::before {
+  content: "\F007A";
+}
+.mdi-robot::before {
+  content: "\F6A8";
+}
+.mdi-robot-industrial::before {
+  content: "\FB21";
+}
+.mdi-robot-mower::before {
+  content: "\F0222";
+}
+.mdi-robot-mower-outline::before {
+  content: "\F021E";
+}
+.mdi-robot-vacuum::before {
+  content: "\F70C";
+}
+.mdi-robot-vacuum-variant::before {
+  content: "\F907";
+}
+.mdi-rocket::before {
+  content: "\F463";
+}
+.mdi-rodent::before {
+  content: "\F0352";
+}
+.mdi-roller-skate::before {
+  content: "\FD07";
+}
+.mdi-rollerblade::before {
+  content: "\FD08";
+}
+.mdi-rollupjs::before {
+  content: "\FB9C";
+}
+.mdi-roman-numeral-1::before {
+  content: "\F00B3";
+}
+.mdi-roman-numeral-10::before {
+  content: "\F00BC";
+}
+.mdi-roman-numeral-2::before {
+  content: "\F00B4";
+}
+.mdi-roman-numeral-3::before {
+  content: "\F00B5";
+}
+.mdi-roman-numeral-4::before {
+  content: "\F00B6";
+}
+.mdi-roman-numeral-5::before {
+  content: "\F00B7";
+}
+.mdi-roman-numeral-6::before {
+  content: "\F00B8";
+}
+.mdi-roman-numeral-7::before {
+  content: "\F00B9";
+}
+.mdi-roman-numeral-8::before {
+  content: "\F00BA";
+}
+.mdi-roman-numeral-9::before {
+  content: "\F00BB";
+}
+.mdi-room-service::before {
+  content: "\F88C";
+}
+.mdi-room-service-outline::before {
+  content: "\FD73";
+}
+.mdi-rotate-3d::before {
+  content: "\FEE4";
+}
+.mdi-rotate-3d-variant::before {
+  content: "\F464";
+}
+.mdi-rotate-left::before {
+  content: "\F465";
+}
+.mdi-rotate-left-variant::before {
+  content: "\F466";
+}
+.mdi-rotate-orbit::before {
+  content: "\FD74";
+}
+.mdi-rotate-right::before {
+  content: "\F467";
+}
+.mdi-rotate-right-variant::before {
+  content: "\F468";
+}
+.mdi-rounded-corner::before {
+  content: "\F607";
+}
+.mdi-router::before {
+  content: "\F020D";
+}
+.mdi-router-wireless::before {
+  content: "\F469";
+}
+.mdi-router-wireless-settings::before {
+  content: "\FA68";
+}
+.mdi-routes::before {
+  content: "\F46A";
+}
+.mdi-routes-clock::before {
+  content: "\F007B";
+}
+.mdi-rowing::before {
+  content: "\F608";
+}
+.mdi-rss::before {
+  content: "\F46B";
+}
+.mdi-rss-box::before {
+  content: "\F46C";
+}
+.mdi-rss-off::before {
+  content: "\FF3E";
+}
+.mdi-ruby::before {
+  content: "\FD09";
+}
+.mdi-rugby::before {
+  content: "\FD75";
+}
+.mdi-ruler::before {
+  content: "\F46D";
+}
+.mdi-ruler-square::before {
+  content: "\FC9E";
+}
+.mdi-ruler-square-compass::before {
+  content: "\FEDB";
+}
+.mdi-run::before {
+  content: "\F70D";
+}
+.mdi-run-fast::before {
+  content: "\F46E";
+}
+.mdi-rv-truck::before {
+  content: "\F01FF";
+}
+.mdi-sack::before {
+  content: "\FD0A";
+}
+.mdi-sack-percent::before {
+  content: "\FD0B";
+}
+.mdi-safe::before {
+  content: "\FA69";
+}
+.mdi-safe-square::before {
+  content: "\F02A7";
+}
+.mdi-safe-square-outline::before {
+  content: "\F02A8";
+}
+.mdi-safety-goggles::before {
+  content: "\FD0C";
+}
+.mdi-sailing::before {
+  content: "\FEE5";
+}
+.mdi-sale::before {
+  content: "\F46F";
+}
+.mdi-salesforce::before {
+  content: "\F88D";
+}
+.mdi-sass::before {
+  content: "\F7EB";
+}
+.mdi-satellite::before {
+  content: "\F470";
+}
+.mdi-satellite-uplink::before {
+  content: "\F908";
+}
+.mdi-satellite-variant::before {
+  content: "\F471";
+}
+.mdi-sausage::before {
+  content: "\F8B9";
+}
+.mdi-saw-blade::before {
+  content: "\FE44";
+}
+.mdi-saxophone::before {
+  content: "\F609";
+}
+.mdi-scale::before {
+  content: "\F472";
+}
+.mdi-scale-balance::before {
+  content: "\F5D1";
+}
+.mdi-scale-bathroom::before {
+  content: "\F473";
+}
+.mdi-scale-off::before {
+  content: "\F007C";
+}
+.mdi-scanner::before {
+  content: "\F6AA";
+}
+.mdi-scanner-off::before {
+  content: "\F909";
+}
+.mdi-scatter-plot::before {
+  content: "\FEE6";
+}
+.mdi-scatter-plot-outline::before {
+  content: "\FEE7";
+}
+.mdi-school::before {
+  content: "\F474";
+}
+.mdi-school-outline::before {
+  content: "\F01AB";
+}
+.mdi-scissors-cutting::before {
+  content: "\FA6A";
+}
+.mdi-scooter::before {
+  content: "\F0214";
+}
+.mdi-scoreboard::before {
+  content: "\F02A9";
+}
+.mdi-scoreboard-outline::before {
+  content: "\F02AA";
+}
+.mdi-screen-rotation::before {
+  content: "\F475";
+}
+.mdi-screen-rotation-lock::before {
+  content: "\F476";
+}
+.mdi-screw-flat-top::before {
+  content: "\FDCF";
+}
+.mdi-screw-lag::before {
+  content: "\FE54";
+}
+.mdi-screw-machine-flat-top::before {
+  content: "\FE55";
+}
+.mdi-screw-machine-round-top::before {
+  content: "\FE56";
+}
+.mdi-screw-round-top::before {
+  content: "\FE57";
+}
+.mdi-screwdriver::before {
+  content: "\F477";
+}
+.mdi-script::before {
+  content: "\FB9D";
+}
+.mdi-script-outline::before {
+  content: "\F478";
+}
+.mdi-script-text::before {
+  content: "\FB9E";
+}
+.mdi-script-text-outline::before {
+  content: "\FB9F";
+}
+.mdi-sd::before {
+  content: "\F479";
+}
+.mdi-seal::before {
+  content: "\F47A";
+}
+.mdi-seal-variant::before {
+  content: "\FFFA";
+}
+.mdi-search-web::before {
+  content: "\F70E";
+}
+.mdi-seat::before {
+  content: "\FC9F";
+}
+.mdi-seat-flat::before {
+  content: "\F47B";
+}
+.mdi-seat-flat-angled::before {
+  content: "\F47C";
+}
+.mdi-seat-individual-suite::before {
+  content: "\F47D";
+}
+.mdi-seat-legroom-extra::before {
+  content: "\F47E";
+}
+.mdi-seat-legroom-normal::before {
+  content: "\F47F";
+}
+.mdi-seat-legroom-reduced::before {
+  content: "\F480";
+}
+.mdi-seat-outline::before {
+  content: "\FCA0";
+}
+.mdi-seat-passenger::before {
+  content: "\F0274";
+}
+.mdi-seat-recline-extra::before {
+  content: "\F481";
+}
+.mdi-seat-recline-normal::before {
+  content: "\F482";
+}
+.mdi-seatbelt::before {
+  content: "\FCA1";
+}
+.mdi-security::before {
+  content: "\F483";
+}
+.mdi-security-network::before {
+  content: "\F484";
+}
+.mdi-seed::before {
+  content: "\FE45";
+}
+.mdi-seed-outline::before {
+  content: "\FE46";
+}
+.mdi-segment::before {
+  content: "\FEE8";
+}
+.mdi-select::before {
+  content: "\F485";
+}
+.mdi-select-all::before {
+  content: "\F486";
+}
+.mdi-select-color::before {
+  content: "\FD0D";
+}
+.mdi-select-compare::before {
+  content: "\FAD8";
+}
+.mdi-select-drag::before {
+  content: "\FA6B";
+}
+.mdi-select-group::before {
+  content: "\FF9F";
+}
+.mdi-select-inverse::before {
+  content: "\F487";
+}
+.mdi-select-marker::before {
+  content: "\F02AB";
+}
+.mdi-select-multiple::before {
+  content: "\F02AC";
+}
+.mdi-select-multiple-marker::before {
+  content: "\F02AD";
+}
+.mdi-select-off::before {
+  content: "\F488";
+}
+.mdi-select-place::before {
+  content: "\FFFB";
+}
+.mdi-select-search::before {
+  content: "\F022F";
+}
+.mdi-selection::before {
+  content: "\F489";
+}
+.mdi-selection-drag::before {
+  content: "\FA6C";
+}
+.mdi-selection-ellipse::before {
+  content: "\FD0E";
+}
+.mdi-selection-ellipse-arrow-inside::before {
+  content: "\FF3F";
+}
+.mdi-selection-marker::before {
+  content: "\F02AE";
+}
+.mdi-selection-multiple-marker::before {
+  content: "\F02AF";
+}
+.mdi-selection-mutliple::before {
+  content: "\F02B0";
+}
+.mdi-selection-off::before {
+  content: "\F776";
+}
+.mdi-selection-search::before {
+  content: "\F0230";
+}
+.mdi-semantic-web::before {
+  content: "\F0341";
+}
+.mdi-send::before {
+  content: "\F48A";
+}
+.mdi-send-check::before {
+  content: "\F018C";
+}
+.mdi-send-check-outline::before {
+  content: "\F018D";
+}
+.mdi-send-circle::before {
+  content: "\FE58";
+}
+.mdi-send-circle-outline::before {
+  content: "\FE59";
+}
+.mdi-send-clock::before {
+  content: "\F018E";
+}
+.mdi-send-clock-outline::before {
+  content: "\F018F";
+}
+.mdi-send-lock::before {
+  content: "\F7EC";
+}
+.mdi-send-lock-outline::before {
+  content: "\F0191";
+}
+.mdi-send-outline::before {
+  content: "\F0190";
+}
+.mdi-serial-port::before {
+  content: "\F65C";
+}
+.mdi-server::before {
+  content: "\F48B";
+}
+.mdi-server-minus::before {
+  content: "\F48C";
+}
+.mdi-server-network::before {
+  content: "\F48D";
+}
+.mdi-server-network-off::before {
+  content: "\F48E";
+}
+.mdi-server-off::before {
+  content: "\F48F";
+}
+.mdi-server-plus::before {
+  content: "\F490";
+}
+.mdi-server-remove::before {
+  content: "\F491";
+}
+.mdi-server-security::before {
+  content: "\F492";
+}
+.mdi-set-all::before {
+  content: "\F777";
+}
+.mdi-set-center::before {
+  content: "\F778";
+}
+.mdi-set-center-right::before {
+  content: "\F779";
+}
+.mdi-set-left::before {
+  content: "\F77A";
+}
+.mdi-set-left-center::before {
+  content: "\F77B";
+}
+.mdi-set-left-right::before {
+  content: "\F77C";
+}
+.mdi-set-none::before {
+  content: "\F77D";
+}
+.mdi-set-right::before {
+  content: "\F77E";
+}
+.mdi-set-top-box::before {
+  content: "\F99E";
+}
+.mdi-settings::before {
+  content: "\F493";
+}
+.mdi-settings-box::before {
+  content: "\F494";
+}
+.mdi-settings-helper::before {
+  content: "\FA6D";
+}
+.mdi-settings-outline::before {
+  content: "\F8BA";
+}
+.mdi-settings-transfer::before {
+  content: "\F007D";
+}
+.mdi-settings-transfer-outline::before {
+  content: "\F007E";
+}
+.mdi-shaker::before {
+  content: "\F0139";
+}
+.mdi-shaker-outline::before {
+  content: "\F013A";
+}
+.mdi-shape::before {
+  content: "\F830";
+}
+.mdi-shape-circle-plus::before {
+  content: "\F65D";
+}
+.mdi-shape-outline::before {
+  content: "\F831";
+}
+.mdi-shape-oval-plus::before {
+  content: "\F0225";
+}
+.mdi-shape-plus::before {
+  content: "\F495";
+}
+.mdi-shape-polygon-plus::before {
+  content: "\F65E";
+}
+.mdi-shape-rectangle-plus::before {
+  content: "\F65F";
+}
+.mdi-shape-square-plus::before {
+  content: "\F660";
+}
+.mdi-share::before {
+  content: "\F496";
+}
+.mdi-share-all::before {
+  content: "\F021F";
+}
+.mdi-share-all-outline::before {
+  content: "\F0220";
+}
+.mdi-share-circle::before {
+  content: "\F01D8";
+}
+.mdi-share-off::before {
+  content: "\FF40";
+}
+.mdi-share-off-outline::before {
+  content: "\FF41";
+}
+.mdi-share-outline::before {
+  content: "\F931";
+}
+.mdi-share-variant::before {
+  content: "\F497";
+}
+.mdi-sheep::before {
+  content: "\FCA2";
+}
+.mdi-shield::before {
+  content: "\F498";
+}
+.mdi-shield-account::before {
+  content: "\F88E";
+}
+.mdi-shield-account-outline::before {
+  content: "\FA11";
+}
+.mdi-shield-airplane::before {
+  content: "\F6BA";
+}
+.mdi-shield-airplane-outline::before {
+  content: "\FCA3";
+}
+.mdi-shield-alert::before {
+  content: "\FEE9";
+}
+.mdi-shield-alert-outline::before {
+  content: "\FEEA";
+}
+.mdi-shield-car::before {
+  content: "\FFA0";
+}
+.mdi-shield-check::before {
+  content: "\F565";
+}
+.mdi-shield-check-outline::before {
+  content: "\FCA4";
+}
+.mdi-shield-cross::before {
+  content: "\FCA5";
+}
+.mdi-shield-cross-outline::before {
+  content: "\FCA6";
+}
+.mdi-shield-edit::before {
+  content: "\F01CB";
+}
+.mdi-shield-edit-outline::before {
+  content: "\F01CC";
+}
+.mdi-shield-half::before {
+  content: "\F038B";
+}
+.mdi-shield-half-full::before {
+  content: "\F77F";
+}
+.mdi-shield-home::before {
+  content: "\F689";
+}
+.mdi-shield-home-outline::before {
+  content: "\FCA7";
+}
+.mdi-shield-key::before {
+  content: "\FBA0";
+}
+.mdi-shield-key-outline::before {
+  content: "\FBA1";
+}
+.mdi-shield-link-variant::before {
+  content: "\FD0F";
+}
+.mdi-shield-link-variant-outline::before {
+  content: "\FD10";
+}
+.mdi-shield-lock::before {
+  content: "\F99C";
+}
+.mdi-shield-lock-outline::before {
+  content: "\FCA8";
+}
+.mdi-shield-off::before {
+  content: "\F99D";
+}
+.mdi-shield-off-outline::before {
+  content: "\F99B";
+}
+.mdi-shield-outline::before {
+  content: "\F499";
+}
+.mdi-shield-plus::before {
+  content: "\FAD9";
+}
+.mdi-shield-plus-outline::before {
+  content: "\FADA";
+}
+.mdi-shield-refresh::before {
+  content: "\F01CD";
+}
+.mdi-shield-refresh-outline::before {
+  content: "\F01CE";
+}
+.mdi-shield-remove::before {
+  content: "\FADB";
+}
+.mdi-shield-remove-outline::before {
+  content: "\FADC";
+}
+.mdi-shield-search::before {
+  content: "\FD76";
+}
+.mdi-shield-star::before {
+  content: "\F0166";
+}
+.mdi-shield-star-outline::before {
+  content: "\F0167";
+}
+.mdi-shield-sun::before {
+  content: "\F007F";
+}
+.mdi-shield-sun-outline::before {
+  content: "\F0080";
+}
+.mdi-ship-wheel::before {
+  content: "\F832";
+}
+.mdi-shoe-formal::before {
+  content: "\FB22";
+}
+.mdi-shoe-heel::before {
+  content: "\FB23";
+}
+.mdi-shoe-print::before {
+  content: "\FE5A";
+}
+.mdi-shopify::before {
+  content: "\FADD";
+}
+.mdi-shopping::before {
+  content: "\F49A";
+}
+.mdi-shopping-music::before {
+  content: "\F49B";
+}
+.mdi-shopping-outline::before {
+  content: "\F0200";
+}
+.mdi-shopping-search::before {
+  content: "\FFA1";
+}
+.mdi-shovel::before {
+  content: "\F70F";
+}
+.mdi-shovel-off::before {
+  content: "\F710";
+}
+.mdi-shower::before {
+  content: "\F99F";
+}
+.mdi-shower-head::before {
+  content: "\F9A0";
+}
+.mdi-shredder::before {
+  content: "\F49C";
+}
+.mdi-shuffle::before {
+  content: "\F49D";
+}
+.mdi-shuffle-disabled::before {
+  content: "\F49E";
+}
+.mdi-shuffle-variant::before {
+  content: "\F49F";
+}
+.mdi-shuriken::before {
+  content: "\F03AA";
+}
+.mdi-sigma::before {
+  content: "\F4A0";
+}
+.mdi-sigma-lower::before {
+  content: "\F62B";
+}
+.mdi-sign-caution::before {
+  content: "\F4A1";
+}
+.mdi-sign-direction::before {
+  content: "\F780";
+}
+.mdi-sign-direction-minus::before {
+  content: "\F0022";
+}
+.mdi-sign-direction-plus::before {
+  content: "\FFFD";
+}
+.mdi-sign-direction-remove::before {
+  content: "\FFFE";
+}
+.mdi-sign-real-estate::before {
+  content: "\F0143";
+}
+.mdi-sign-text::before {
+  content: "\F781";
+}
+.mdi-signal::before {
+  content: "\F4A2";
+}
+.mdi-signal-2g::before {
+  content: "\F711";
+}
+.mdi-signal-3g::before {
+  content: "\F712";
+}
+.mdi-signal-4g::before {
+  content: "\F713";
+}
+.mdi-signal-5g::before {
+  content: "\FA6E";
+}
+.mdi-signal-cellular-1::before {
+  content: "\F8BB";
+}
+.mdi-signal-cellular-2::before {
+  content: "\F8BC";
+}
+.mdi-signal-cellular-3::before {
+  content: "\F8BD";
+}
+.mdi-signal-cellular-outline::before {
+  content: "\F8BE";
+}
+.mdi-signal-distance-variant::before {
+  content: "\FE47";
+}
+.mdi-signal-hspa::before {
+  content: "\F714";
+}
+.mdi-signal-hspa-plus::before {
+  content: "\F715";
+}
+.mdi-signal-off::before {
+  content: "\F782";
+}
+.mdi-signal-variant::before {
+  content: "\F60A";
+}
+.mdi-signature::before {
+  content: "\FE5B";
+}
+.mdi-signature-freehand::before {
+  content: "\FE5C";
+}
+.mdi-signature-image::before {
+  content: "\FE5D";
+}
+.mdi-signature-text::before {
+  content: "\FE5E";
+}
+.mdi-silo::before {
+  content: "\FB24";
+}
+.mdi-silverware::before {
+  content: "\F4A3";
+}
+.mdi-silverware-clean::before {
+  content: "\FFFF";
+}
+.mdi-silverware-fork::before {
+  content: "\F4A4";
+}
+.mdi-silverware-fork-knife::before {
+  content: "\FA6F";
+}
+.mdi-silverware-spoon::before {
+  content: "\F4A5";
+}
+.mdi-silverware-variant::before {
+  content: "\F4A6";
+}
+.mdi-sim::before {
+  content: "\F4A7";
+}
+.mdi-sim-alert::before {
+  content: "\F4A8";
+}
+.mdi-sim-off::before {
+  content: "\F4A9";
+}
+.mdi-simple-icons::before {
+  content: "\F0348";
+}
+.mdi-sina-weibo::before {
+  content: "\FADE";
+}
+.mdi-sitemap::before {
+  content: "\F4AA";
+}
+.mdi-skate::before {
+  content: "\FD11";
+}
+.mdi-skew-less::before {
+  content: "\FD12";
+}
+.mdi-skew-more::before {
+  content: "\FD13";
+}
+.mdi-ski::before {
+  content: "\F032F";
+}
+.mdi-ski-cross-country::before {
+  content: "\F0330";
+}
+.mdi-ski-water::before {
+  content: "\F0331";
+}
+.mdi-skip-backward::before {
+  content: "\F4AB";
+}
+.mdi-skip-backward-outline::before {
+  content: "\FF42";
+}
+.mdi-skip-forward::before {
+  content: "\F4AC";
+}
+.mdi-skip-forward-outline::before {
+  content: "\FF43";
+}
+.mdi-skip-next::before {
+  content: "\F4AD";
+}
+.mdi-skip-next-circle::before {
+  content: "\F661";
+}
+.mdi-skip-next-circle-outline::before {
+  content: "\F662";
+}
+.mdi-skip-next-outline::before {
+  content: "\FF44";
+}
+.mdi-skip-previous::before {
+  content: "\F4AE";
+}
+.mdi-skip-previous-circle::before {
+  content: "\F663";
+}
+.mdi-skip-previous-circle-outline::before {
+  content: "\F664";
+}
+.mdi-skip-previous-outline::before {
+  content: "\FF45";
+}
+.mdi-skull::before {
+  content: "\F68B";
+}
+.mdi-skull-crossbones::before {
+  content: "\FBA2";
+}
+.mdi-skull-crossbones-outline::before {
+  content: "\FBA3";
+}
+.mdi-skull-outline::before {
+  content: "\FBA4";
+}
+.mdi-skype::before {
+  content: "\F4AF";
+}
+.mdi-skype-business::before {
+  content: "\F4B0";
+}
+.mdi-slack::before {
+  content: "\F4B1";
+}
+.mdi-slackware::before {
+  content: "\F90A";
+}
+.mdi-slash-forward::before {
+  content: "\F0000";
+}
+.mdi-slash-forward-box::before {
+  content: "\F0001";
+}
+.mdi-sleep::before {
+  content: "\F4B2";
+}
+.mdi-sleep-off::before {
+  content: "\F4B3";
+}
+.mdi-slope-downhill::before {
+  content: "\FE5F";
+}
+.mdi-slope-uphill::before {
+  content: "\FE60";
+}
+.mdi-slot-machine::before {
+  content: "\F013F";
+}
+.mdi-slot-machine-outline::before {
+  content: "\F0140";
+}
+.mdi-smart-card::before {
+  content: "\F00E8";
+}
+.mdi-smart-card-outline::before {
+  content: "\F00E9";
+}
+.mdi-smart-card-reader::before {
+  content: "\F00EA";
+}
+.mdi-smart-card-reader-outline::before {
+  content: "\F00EB";
+}
+.mdi-smog::before {
+  content: "\FA70";
+}
+.mdi-smoke-detector::before {
+  content: "\F392";
+}
+.mdi-smoking::before {
+  content: "\F4B4";
+}
+.mdi-smoking-off::before {
+  content: "\F4B5";
+}
+.mdi-snapchat::before {
+  content: "\F4B6";
+}
+.mdi-snowboard::before {
+  content: "\F0332";
+}
+.mdi-snowflake::before {
+  content: "\F716";
+}
+.mdi-snowflake-alert::before {
+  content: "\FF46";
+}
+.mdi-snowflake-melt::before {
+  content: "\F02F6";
+}
+.mdi-snowflake-variant::before {
+  content: "\FF47";
+}
+.mdi-snowman::before {
+  content: "\F4B7";
+}
+.mdi-soccer::before {
+  content: "\F4B8";
+}
+.mdi-soccer-field::before {
+  content: "\F833";
+}
+.mdi-sofa::before {
+  content: "\F4B9";
+}
+.mdi-solar-panel::before {
+  content: "\FD77";
+}
+.mdi-solar-panel-large::before {
+  content: "\FD78";
+}
+.mdi-solar-power::before {
+  content: "\FA71";
+}
+.mdi-soldering-iron::before {
+  content: "\F00BD";
+}
+.mdi-solid::before {
+  content: "\F68C";
+}
+.mdi-sort::before {
+  content: "\F4BA";
+}
+.mdi-sort-alphabetical::before {
+  content: "\F4BB";
+}
+.mdi-sort-alphabetical-ascending::before {
+  content: "\F0173";
+}
+.mdi-sort-alphabetical-descending::before {
+  content: "\F0174";
+}
+.mdi-sort-ascending::before {
+  content: "\F4BC";
+}
+.mdi-sort-descending::before {
+  content: "\F4BD";
+}
+.mdi-sort-numeric::before {
+  content: "\F4BE";
+}
+.mdi-sort-variant::before {
+  content: "\F4BF";
+}
+.mdi-sort-variant-lock::before {
+  content: "\FCA9";
+}
+.mdi-sort-variant-lock-open::before {
+  content: "\FCAA";
+}
+.mdi-sort-variant-remove::before {
+  content: "\F0172";
+}
+.mdi-soundcloud::before {
+  content: "\F4C0";
+}
+.mdi-source-branch::before {
+  content: "\F62C";
+}
+.mdi-source-commit::before {
+  content: "\F717";
+}
+.mdi-source-commit-end::before {
+  content: "\F718";
+}
+.mdi-source-commit-end-local::before {
+  content: "\F719";
+}
+.mdi-source-commit-local::before {
+  content: "\F71A";
+}
+.mdi-source-commit-next-local::before {
+  content: "\F71B";
+}
+.mdi-source-commit-start::before {
+  content: "\F71C";
+}
+.mdi-source-commit-start-next-local::before {
+  content: "\F71D";
+}
+.mdi-source-fork::before {
+  content: "\F4C1";
+}
+.mdi-source-merge::before {
+  content: "\F62D";
+}
+.mdi-source-pull::before {
+  content: "\F4C2";
+}
+.mdi-source-repository::before {
+  content: "\FCAB";
+}
+.mdi-source-repository-multiple::before {
+  content: "\FCAC";
+}
+.mdi-soy-sauce::before {
+  content: "\F7ED";
+}
+.mdi-spa::before {
+  content: "\FCAD";
+}
+.mdi-spa-outline::before {
+  content: "\FCAE";
+}
+.mdi-space-invaders::before {
+  content: "\FBA5";
+}
+.mdi-space-station::before {
+  content: "\F03AE";
+}
+.mdi-spade::before {
+  content: "\FE48";
+}
+.mdi-speaker::before {
+  content: "\F4C3";
+}
+.mdi-speaker-bluetooth::before {
+  content: "\F9A1";
+}
+.mdi-speaker-multiple::before {
+  content: "\FD14";
+}
+.mdi-speaker-off::before {
+  content: "\F4C4";
+}
+.mdi-speaker-wireless::before {
+  content: "\F71E";
+}
+.mdi-speedometer::before {
+  content: "\F4C5";
+}
+.mdi-speedometer-medium::before {
+  content: "\FFA2";
+}
+.mdi-speedometer-slow::before {
+  content: "\FFA3";
+}
+.mdi-spellcheck::before {
+  content: "\F4C6";
+}
+.mdi-spider::before {
+  content: "\F0215";
+}
+.mdi-spider-thread::before {
+  content: "\F0216";
+}
+.mdi-spider-web::before {
+  content: "\FBA6";
+}
+.mdi-spotify::before {
+  content: "\F4C7";
+}
+.mdi-spotlight::before {
+  content: "\F4C8";
+}
+.mdi-spotlight-beam::before {
+  content: "\F4C9";
+}
+.mdi-spray::before {
+  content: "\F665";
+}
+.mdi-spray-bottle::before {
+  content: "\FADF";
+}
+.mdi-sprinkler::before {
+  content: "\F0081";
+}
+.mdi-sprinkler-variant::before {
+  content: "\F0082";
+}
+.mdi-sprout::before {
+  content: "\FE49";
+}
+.mdi-sprout-outline::before {
+  content: "\FE4A";
+}
+.mdi-square::before {
+  content: "\F763";
+}
+.mdi-square-edit-outline::before {
+  content: "\F90B";
+}
+.mdi-square-inc::before {
+  content: "\F4CA";
+}
+.mdi-square-inc-cash::before {
+  content: "\F4CB";
+}
+.mdi-square-medium::before {
+  content: "\FA12";
+}
+.mdi-square-medium-outline::before {
+  content: "\FA13";
+}
+.mdi-square-off::before {
+  content: "\F0319";
+}
+.mdi-square-off-outline::before {
+  content: "\F031A";
+}
+.mdi-square-outline::before {
+  content: "\F762";
+}
+.mdi-square-root::before {
+  content: "\F783";
+}
+.mdi-square-root-box::before {
+  content: "\F9A2";
+}
+.mdi-square-small::before {
+  content: "\FA14";
+}
+.mdi-squeegee::before {
+  content: "\FAE0";
+}
+.mdi-ssh::before {
+  content: "\F8BF";
+}
+.mdi-stack-exchange::before {
+  content: "\F60B";
+}
+.mdi-stack-overflow::before {
+  content: "\F4CC";
+}
+.mdi-stackpath::before {
+  content: "\F359";
+}
+.mdi-stadium::before {
+  content: "\F001A";
+}
+.mdi-stadium-variant::before {
+  content: "\F71F";
+}
+.mdi-stairs::before {
+  content: "\F4CD";
+}
+.mdi-stairs-down::before {
+  content: "\F02E9";
+}
+.mdi-stairs-up::before {
+  content: "\F02E8";
+}
+.mdi-stamper::before {
+  content: "\FD15";
+}
+.mdi-standard-definition::before {
+  content: "\F7EE";
+}
+.mdi-star::before {
+  content: "\F4CE";
+}
+.mdi-star-box::before {
+  content: "\FA72";
+}
+.mdi-star-box-multiple::before {
+  content: "\F02B1";
+}
+.mdi-star-box-multiple-outline::before {
+  content: "\F02B2";
+}
+.mdi-star-box-outline::before {
+  content: "\FA73";
+}
+.mdi-star-circle::before {
+  content: "\F4CF";
+}
+.mdi-star-circle-outline::before {
+  content: "\F9A3";
+}
+.mdi-star-face::before {
+  content: "\F9A4";
+}
+.mdi-star-four-points::before {
+  content: "\FAE1";
+}
+.mdi-star-four-points-outline::before {
+  content: "\FAE2";
+}
+.mdi-star-half::before {
+  content: "\F4D0";
+}
+.mdi-star-off::before {
+  content: "\F4D1";
+}
+.mdi-star-outline::before {
+  content: "\F4D2";
+}
+.mdi-star-three-points::before {
+  content: "\FAE3";
+}
+.mdi-star-three-points-outline::before {
+  content: "\FAE4";
+}
+.mdi-state-machine::before {
+  content: "\F021A";
+}
+.mdi-steam::before {
+  content: "\F4D3";
+}
+.mdi-steam-box::before {
+  content: "\F90C";
+}
+.mdi-steering::before {
+  content: "\F4D4";
+}
+.mdi-steering-off::before {
+  content: "\F90D";
+}
+.mdi-step-backward::before {
+  content: "\F4D5";
+}
+.mdi-step-backward-2::before {
+  content: "\F4D6";
+}
+.mdi-step-forward::before {
+  content: "\F4D7";
+}
+.mdi-step-forward-2::before {
+  content: "\F4D8";
+}
+.mdi-stethoscope::before {
+  content: "\F4D9";
+}
+.mdi-sticker::before {
+  content: "\F038F";
+}
+.mdi-sticker-alert::before {
+  content: "\F0390";
+}
+.mdi-sticker-alert-outline::before {
+  content: "\F0391";
+}
+.mdi-sticker-check::before {
+  content: "\F0392";
+}
+.mdi-sticker-check-outline::before {
+  content: "\F0393";
+}
+.mdi-sticker-circle-outline::before {
+  content: "\F5D0";
+}
+.mdi-sticker-emoji::before {
+  content: "\F784";
+}
+.mdi-sticker-minus::before {
+  content: "\F0394";
+}
+.mdi-sticker-minus-outline::before {
+  content: "\F0395";
+}
+.mdi-sticker-outline::before {
+  content: "\F0396";
+}
+.mdi-sticker-plus::before {
+  content: "\F0397";
+}
+.mdi-sticker-plus-outline::before {
+  content: "\F0398";
+}
+.mdi-sticker-remove::before {
+  content: "\F0399";
+}
+.mdi-sticker-remove-outline::before {
+  content: "\F039A";
+}
+.mdi-stocking::before {
+  content: "\F4DA";
+}
+.mdi-stomach::before {
+  content: "\F00BE";
+}
+.mdi-stop::before {
+  content: "\F4DB";
+}
+.mdi-stop-circle::before {
+  content: "\F666";
+}
+.mdi-stop-circle-outline::before {
+  content: "\F667";
+}
+.mdi-store::before {
+  content: "\F4DC";
+}
+.mdi-store-24-hour::before {
+  content: "\F4DD";
+}
+.mdi-store-outline::before {
+  content: "\F038C";
+}
+.mdi-storefront::before {
+  content: "\F00EC";
+}
+.mdi-stove::before {
+  content: "\F4DE";
+}
+.mdi-strategy::before {
+  content: "\F0201";
+}
+.mdi-strava::before {
+  content: "\FB25";
+}
+.mdi-stretch-to-page::before {
+  content: "\FF48";
+}
+.mdi-stretch-to-page-outline::before {
+  content: "\FF49";
+}
+.mdi-string-lights::before {
+  content: "\F02E5";
+}
+.mdi-string-lights-off::before {
+  content: "\F02E6";
+}
+.mdi-subdirectory-arrow-left::before {
+  content: "\F60C";
+}
+.mdi-subdirectory-arrow-right::before {
+  content: "\F60D";
+}
+.mdi-subtitles::before {
+  content: "\FA15";
+}
+.mdi-subtitles-outline::before {
+  content: "\FA16";
+}
+.mdi-subway::before {
+  content: "\F6AB";
+}
+.mdi-subway-alert-variant::before {
+  content: "\FD79";
+}
+.mdi-subway-variant::before {
+  content: "\F4DF";
+}
+.mdi-summit::before {
+  content: "\F785";
+}
+.mdi-sunglasses::before {
+  content: "\F4E0";
+}
+.mdi-surround-sound::before {
+  content: "\F5C5";
+}
+.mdi-surround-sound-2-0::before {
+  content: "\F7EF";
+}
+.mdi-surround-sound-3-1::before {
+  content: "\F7F0";
+}
+.mdi-surround-sound-5-1::before {
+  content: "\F7F1";
+}
+.mdi-surround-sound-7-1::before {
+  content: "\F7F2";
+}
+.mdi-svg::before {
+  content: "\F720";
+}
+.mdi-swap-horizontal::before {
+  content: "\F4E1";
+}
+.mdi-swap-horizontal-bold::before {
+  content: "\FBA9";
+}
+.mdi-swap-horizontal-circle::before {
+  content: "\F0002";
+}
+.mdi-swap-horizontal-circle-outline::before {
+  content: "\F0003";
+}
+.mdi-swap-horizontal-variant::before {
+  content: "\F8C0";
+}
+.mdi-swap-vertical::before {
+  content: "\F4E2";
+}
+.mdi-swap-vertical-bold::before {
+  content: "\FBAA";
+}
+.mdi-swap-vertical-circle::before {
+  content: "\F0004";
+}
+.mdi-swap-vertical-circle-outline::before {
+  content: "\F0005";
+}
+.mdi-swap-vertical-variant::before {
+  content: "\F8C1";
+}
+.mdi-swim::before {
+  content: "\F4E3";
+}
+.mdi-switch::before {
+  content: "\F4E4";
+}
+.mdi-sword::before {
+  content: "\F4E5";
+}
+.mdi-sword-cross::before {
+  content: "\F786";
+}
+.mdi-syllabary-hangul::before {
+  content: "\F035E";
+}
+.mdi-syllabary-hiragana::before {
+  content: "\F035F";
+}
+.mdi-syllabary-katakana::before {
+  content: "\F0360";
+}
+.mdi-syllabary-katakana-half-width::before {
+  content: "\F0361";
+}
+.mdi-symfony::before {
+  content: "\FAE5";
+}
+.mdi-sync::before {
+  content: "\F4E6";
+}
+.mdi-sync-alert::before {
+  content: "\F4E7";
+}
+.mdi-sync-circle::before {
+  content: "\F03A3";
+}
+.mdi-sync-off::before {
+  content: "\F4E8";
+}
+.mdi-tab::before {
+  content: "\F4E9";
+}
+.mdi-tab-minus::before {
+  content: "\FB26";
+}
+.mdi-tab-plus::before {
+  content: "\F75B";
+}
+.mdi-tab-remove::before {
+  content: "\FB27";
+}
+.mdi-tab-unselected::before {
+  content: "\F4EA";
+}
+.mdi-table::before {
+  content: "\F4EB";
+}
+.mdi-table-border::before {
+  content: "\FA17";
+}
+.mdi-table-chair::before {
+  content: "\F0083";
+}
+.mdi-table-column::before {
+  content: "\F834";
+}
+.mdi-table-column-plus-after::before {
+  content: "\F4EC";
+}
+.mdi-table-column-plus-before::before {
+  content: "\F4ED";
+}
+.mdi-table-column-remove::before {
+  content: "\F4EE";
+}
+.mdi-table-column-width::before {
+  content: "\F4EF";
+}
+.mdi-table-edit::before {
+  content: "\F4F0";
+}
+.mdi-table-eye::before {
+  content: "\F00BF";
+}
+.mdi-table-headers-eye::before {
+  content: "\F0248";
+}
+.mdi-table-headers-eye-off::before {
+  content: "\F0249";
+}
+.mdi-table-large::before {
+  content: "\F4F1";
+}
+.mdi-table-large-plus::before {
+  content: "\FFA4";
+}
+.mdi-table-large-remove::before {
+  content: "\FFA5";
+}
+.mdi-table-merge-cells::before {
+  content: "\F9A5";
+}
+.mdi-table-of-contents::before {
+  content: "\F835";
+}
+.mdi-table-plus::before {
+  content: "\FA74";
+}
+.mdi-table-remove::before {
+  content: "\FA75";
+}
+.mdi-table-row::before {
+  content: "\F836";
+}
+.mdi-table-row-height::before {
+  content: "\F4F2";
+}
+.mdi-table-row-plus-after::before {
+  content: "\F4F3";
+}
+.mdi-table-row-plus-before::before {
+  content: "\F4F4";
+}
+.mdi-table-row-remove::before {
+  content: "\F4F5";
+}
+.mdi-table-search::before {
+  content: "\F90E";
+}
+.mdi-table-settings::before {
+  content: "\F837";
+}
+.mdi-table-tennis::before {
+  content: "\FE4B";
+}
+.mdi-tablet::before {
+  content: "\F4F6";
+}
+.mdi-tablet-android::before {
+  content: "\F4F7";
+}
+.mdi-tablet-cellphone::before {
+  content: "\F9A6";
+}
+.mdi-tablet-dashboard::before {
+  content: "\FEEB";
+}
+.mdi-tablet-ipad::before {
+  content: "\F4F8";
+}
+.mdi-taco::before {
+  content: "\F761";
+}
+.mdi-tag::before {
+  content: "\F4F9";
+}
+.mdi-tag-faces::before {
+  content: "\F4FA";
+}
+.mdi-tag-heart::before {
+  content: "\F68A";
+}
+.mdi-tag-heart-outline::before {
+  content: "\FBAB";
+}
+.mdi-tag-minus::before {
+  content: "\F90F";
+}
+.mdi-tag-minus-outline::before {
+  content: "\F024A";
+}
+.mdi-tag-multiple::before {
+  content: "\F4FB";
+}
+.mdi-tag-multiple-outline::before {
+  content: "\F0322";
+}
+.mdi-tag-off::before {
+  content: "\F024B";
+}
+.mdi-tag-off-outline::before {
+  content: "\F024C";
+}
+.mdi-tag-outline::before {
+  content: "\F4FC";
+}
+.mdi-tag-plus::before {
+  content: "\F721";
+}
+.mdi-tag-plus-outline::before {
+  content: "\F024D";
+}
+.mdi-tag-remove::before {
+  content: "\F722";
+}
+.mdi-tag-remove-outline::before {
+  content: "\F024E";
+}
+.mdi-tag-text::before {
+  content: "\F024F";
+}
+.mdi-tag-text-outline::before {
+  content: "\F4FD";
+}
+.mdi-tank::before {
+  content: "\FD16";
+}
+.mdi-tanker-truck::before {
+  content: "\F0006";
+}
+.mdi-tape-measure::before {
+  content: "\FB28";
+}
+.mdi-target::before {
+  content: "\F4FE";
+}
+.mdi-target-account::before {
+  content: "\FBAC";
+}
+.mdi-target-variant::before {
+  content: "\FA76";
+}
+.mdi-taxi::before {
+  content: "\F4FF";
+}
+.mdi-tea::before {
+  content: "\FD7A";
+}
+.mdi-tea-outline::before {
+  content: "\FD7B";
+}
+.mdi-teach::before {
+  content: "\F88F";
+}
+.mdi-teamviewer::before {
+  content: "\F500";
+}
+.mdi-telegram::before {
+  content: "\F501";
+}
+.mdi-telescope::before {
+  content: "\FB29";
+}
+.mdi-television::before {
+  content: "\F502";
+}
+.mdi-television-ambient-light::before {
+  content: "\F0381";
+}
+.mdi-television-box::before {
+  content: "\F838";
+}
+.mdi-television-classic::before {
+  content: "\F7F3";
+}
+.mdi-television-classic-off::before {
+  content: "\F839";
+}
+.mdi-television-clean::before {
+  content: "\F013B";
+}
+.mdi-television-guide::before {
+  content: "\F503";
+}
+.mdi-television-off::before {
+  content: "\F83A";
+}
+.mdi-television-pause::before {
+  content: "\FFA6";
+}
+.mdi-television-play::before {
+  content: "\FEEC";
+}
+.mdi-television-stop::before {
+  content: "\FFA7";
+}
+.mdi-temperature-celsius::before {
+  content: "\F504";
+}
+.mdi-temperature-fahrenheit::before {
+  content: "\F505";
+}
+.mdi-temperature-kelvin::before {
+  content: "\F506";
+}
+.mdi-tennis::before {
+  content: "\FD7C";
+}
+.mdi-tennis-ball::before {
+  content: "\F507";
+}
+.mdi-tent::before {
+  content: "\F508";
+}
+.mdi-terraform::before {
+  content: "\F0084";
+}
+.mdi-terrain::before {
+  content: "\F509";
+}
+.mdi-test-tube::before {
+  content: "\F668";
+}
+.mdi-test-tube-empty::before {
+  content: "\F910";
+}
+.mdi-test-tube-off::before {
+  content: "\F911";
+}
+.mdi-text::before {
+  content: "\F9A7";
+}
+.mdi-text-recognition::before {
+  content: "\F0168";
+}
+.mdi-text-shadow::before {
+  content: "\F669";
+}
+.mdi-text-short::before {
+  content: "\F9A8";
+}
+.mdi-text-subject::before {
+  content: "\F9A9";
+}
+.mdi-text-to-speech::before {
+  content: "\F50A";
+}
+.mdi-text-to-speech-off::before {
+  content: "\F50B";
+}
+.mdi-textarea::before {
+  content: "\F00C0";
+}
+.mdi-textbox::before {
+  content: "\F60E";
+}
+.mdi-textbox-lock::before {
+  content: "\F0388";
+}
+.mdi-textbox-password::before {
+  content: "\F7F4";
+}
+.mdi-texture::before {
+  content: "\F50C";
+}
+.mdi-texture-box::before {
+  content: "\F0007";
+}
+.mdi-theater::before {
+  content: "\F50D";
+}
+.mdi-theme-light-dark::before {
+  content: "\F50E";
+}
+.mdi-thermometer::before {
+  content: "\F50F";
+}
+.mdi-thermometer-alert::before {
+  content: "\FE61";
+}
+.mdi-thermometer-chevron-down::before {
+  content: "\FE62";
+}
+.mdi-thermometer-chevron-up::before {
+  content: "\FE63";
+}
+.mdi-thermometer-high::before {
+  content: "\F00ED";
+}
+.mdi-thermometer-lines::before {
+  content: "\F510";
+}
+.mdi-thermometer-low::before {
+  content: "\F00EE";
+}
+.mdi-thermometer-minus::before {
+  content: "\FE64";
+}
+.mdi-thermometer-plus::before {
+  content: "\FE65";
+}
+.mdi-thermostat::before {
+  content: "\F393";
+}
+.mdi-thermostat-box::before {
+  content: "\F890";
+}
+.mdi-thought-bubble::before {
+  content: "\F7F5";
+}
+.mdi-thought-bubble-outline::before {
+  content: "\F7F6";
+}
+.mdi-thumb-down::before {
+  content: "\F511";
+}
+.mdi-thumb-down-outline::before {
+  content: "\F512";
+}
+.mdi-thumb-up::before {
+  content: "\F513";
+}
+.mdi-thumb-up-outline::before {
+  content: "\F514";
+}
+.mdi-thumbs-up-down::before {
+  content: "\F515";
+}
+.mdi-ticket::before {
+  content: "\F516";
+}
+.mdi-ticket-account::before {
+  content: "\F517";
+}
+.mdi-ticket-confirmation::before {
+  content: "\F518";
+}
+.mdi-ticket-outline::before {
+  content: "\F912";
+}
+.mdi-ticket-percent::before {
+  content: "\F723";
+}
+.mdi-tie::before {
+  content: "\F519";
+}
+.mdi-tilde::before {
+  content: "\F724";
+}
+.mdi-timelapse::before {
+  content: "\F51A";
+}
+.mdi-timeline::before {
+  content: "\FBAD";
+}
+.mdi-timeline-alert::before {
+  content: "\FFB2";
+}
+.mdi-timeline-alert-outline::before {
+  content: "\FFB5";
+}
+.mdi-timeline-clock::before {
+  content: "\F0226";
+}
+.mdi-timeline-clock-outline::before {
+  content: "\F0227";
+}
+.mdi-timeline-help::before {
+  content: "\FFB6";
+}
+.mdi-timeline-help-outline::before {
+  content: "\FFB7";
+}
+.mdi-timeline-outline::before {
+  content: "\FBAE";
+}
+.mdi-timeline-plus::before {
+  content: "\FFB3";
+}
+.mdi-timeline-plus-outline::before {
+  content: "\FFB4";
+}
+.mdi-timeline-text::before {
+  content: "\FBAF";
+}
+.mdi-timeline-text-outline::before {
+  content: "\FBB0";
+}
+.mdi-timer::before {
+  content: "\F51B";
+}
+.mdi-timer-10::before {
+  content: "\F51C";
+}
+.mdi-timer-3::before {
+  content: "\F51D";
+}
+.mdi-timer-off::before {
+  content: "\F51E";
+}
+.mdi-timer-sand::before {
+  content: "\F51F";
+}
+.mdi-timer-sand-empty::before {
+  content: "\F6AC";
+}
+.mdi-timer-sand-full::before {
+  content: "\F78B";
+}
+.mdi-timetable::before {
+  content: "\F520";
+}
+.mdi-toaster::before {
+  content: "\F0085";
+}
+.mdi-toaster-off::before {
+  content: "\F01E2";
+}
+.mdi-toaster-oven::before {
+  content: "\FCAF";
+}
+.mdi-toggle-switch::before {
+  content: "\F521";
+}
+.mdi-toggle-switch-off::before {
+  content: "\F522";
+}
+.mdi-toggle-switch-off-outline::before {
+  content: "\FA18";
+}
+.mdi-toggle-switch-outline::before {
+  content: "\FA19";
+}
+.mdi-toilet::before {
+  content: "\F9AA";
+}
+.mdi-toolbox::before {
+  content: "\F9AB";
+}
+.mdi-toolbox-outline::before {
+  content: "\F9AC";
+}
+.mdi-tools::before {
+  content: "\F0086";
+}
+.mdi-tooltip::before {
+  content: "\F523";
+}
+.mdi-tooltip-account::before {
+  content: "\F00C";
+}
+.mdi-tooltip-edit::before {
+  content: "\F524";
+}
+.mdi-tooltip-edit-outline::before {
+  content: "\F02F0";
+}
+.mdi-tooltip-image::before {
+  content: "\F525";
+}
+.mdi-tooltip-image-outline::before {
+  content: "\FBB1";
+}
+.mdi-tooltip-outline::before {
+  content: "\F526";
+}
+.mdi-tooltip-plus::before {
+  content: "\FBB2";
+}
+.mdi-tooltip-plus-outline::before {
+  content: "\F527";
+}
+.mdi-tooltip-text::before {
+  content: "\F528";
+}
+.mdi-tooltip-text-outline::before {
+  content: "\FBB3";
+}
+.mdi-tooth::before {
+  content: "\F8C2";
+}
+.mdi-tooth-outline::before {
+  content: "\F529";
+}
+.mdi-toothbrush::before {
+  content: "\F0154";
+}
+.mdi-toothbrush-electric::before {
+  content: "\F0157";
+}
+.mdi-toothbrush-paste::before {
+  content: "\F0155";
+}
+.mdi-tor::before {
+  content: "\F52A";
+}
+.mdi-tortoise::before {
+  content: "\FD17";
+}
+.mdi-toslink::before {
+  content: "\F02E3";
+}
+.mdi-tournament::before {
+  content: "\F9AD";
+}
+.mdi-tower-beach::before {
+  content: "\F680";
+}
+.mdi-tower-fire::before {
+  content: "\F681";
+}
+.mdi-towing::before {
+  content: "\F83B";
+}
+.mdi-toy-brick::before {
+  content: "\F02B3";
+}
+.mdi-toy-brick-marker::before {
+  content: "\F02B4";
+}
+.mdi-toy-brick-marker-outline::before {
+  content: "\F02B5";
+}
+.mdi-toy-brick-minus::before {
+  content: "\F02B6";
+}
+.mdi-toy-brick-minus-outline::before {
+  content: "\F02B7";
+}
+.mdi-toy-brick-outline::before {
+  content: "\F02B8";
+}
+.mdi-toy-brick-plus::before {
+  content: "\F02B9";
+}
+.mdi-toy-brick-plus-outline::before {
+  content: "\F02BA";
+}
+.mdi-toy-brick-remove::before {
+  content: "\F02BB";
+}
+.mdi-toy-brick-remove-outline::before {
+  content: "\F02BC";
+}
+.mdi-toy-brick-search::before {
+  content: "\F02BD";
+}
+.mdi-toy-brick-search-outline::before {
+  content: "\F02BE";
+}
+.mdi-track-light::before {
+  content: "\F913";
+}
+.mdi-trackpad::before {
+  content: "\F7F7";
+}
+.mdi-trackpad-lock::before {
+  content: "\F932";
+}
+.mdi-tractor::before {
+  content: "\F891";
+}
+.mdi-trademark::before {
+  content: "\FA77";
+}
+.mdi-traffic-cone::before {
+  content: "\F03A7";
+}
+.mdi-traffic-light::before {
+  content: "\F52B";
+}
+.mdi-train::before {
+  content: "\F52C";
+}
+.mdi-train-car::before {
+  content: "\FBB4";
+}
+.mdi-train-variant::before {
+  content: "\F8C3";
+}
+.mdi-tram::before {
+  content: "\F52D";
+}
+.mdi-tram-side::before {
+  content: "\F0008";
+}
+.mdi-transcribe::before {
+  content: "\F52E";
+}
+.mdi-transcribe-close::before {
+  content: "\F52F";
+}
+.mdi-transfer::before {
+  content: "\F0087";
+}
+.mdi-transfer-down::before {
+  content: "\FD7D";
+}
+.mdi-transfer-left::before {
+  content: "\FD7E";
+}
+.mdi-transfer-right::before {
+  content: "\F530";
+}
+.mdi-transfer-up::before {
+  content: "\FD7F";
+}
+.mdi-transit-connection::before {
+  content: "\FD18";
+}
+.mdi-transit-connection-variant::before {
+  content: "\FD19";
+}
+.mdi-transit-detour::before {
+  content: "\FFA8";
+}
+.mdi-transit-transfer::before {
+  content: "\F6AD";
+}
+.mdi-transition::before {
+  content: "\F914";
+}
+.mdi-transition-masked::before {
+  content: "\F915";
+}
+.mdi-translate::before {
+  content: "\F5CA";
+}
+.mdi-translate-off::before {
+  content: "\FE66";
+}
+.mdi-transmission-tower::before {
+  content: "\FD1A";
+}
+.mdi-trash-can::before {
+  content: "\FA78";
+}
+.mdi-trash-can-outline::before {
+  content: "\FA79";
+}
+.mdi-tray::before {
+  content: "\F02BF";
+}
+.mdi-tray-alert::before {
+  content: "\F02C0";
+}
+.mdi-tray-full::before {
+  content: "\F02C1";
+}
+.mdi-tray-minus::before {
+  content: "\F02C2";
+}
+.mdi-tray-plus::before {
+  content: "\F02C3";
+}
+.mdi-tray-remove::before {
+  content: "\F02C4";
+}
+.mdi-treasure-chest::before {
+  content: "\F725";
+}
+.mdi-tree::before {
+  content: "\F531";
+}
+.mdi-tree-outline::before {
+  content: "\FE4C";
+}
+.mdi-trello::before {
+  content: "\F532";
+}
+.mdi-trending-down::before {
+  content: "\F533";
+}
+.mdi-trending-neutral::before {
+  content: "\F534";
+}
+.mdi-trending-up::before {
+  content: "\F535";
+}
+.mdi-triangle::before {
+  content: "\F536";
+}
+.mdi-triangle-outline::before {
+  content: "\F537";
+}
+.mdi-triforce::before {
+  content: "\FBB5";
+}
+.mdi-trophy::before {
+  content: "\F538";
+}
+.mdi-trophy-award::before {
+  content: "\F539";
+}
+.mdi-trophy-broken::before {
+  content: "\FD80";
+}
+.mdi-trophy-outline::before {
+  content: "\F53A";
+}
+.mdi-trophy-variant::before {
+  content: "\F53B";
+}
+.mdi-trophy-variant-outline::before {
+  content: "\F53C";
+}
+.mdi-truck::before {
+  content: "\F53D";
+}
+.mdi-truck-check::before {
+  content: "\FCB0";
+}
+.mdi-truck-check-outline::before {
+  content: "\F02C5";
+}
+.mdi-truck-delivery::before {
+  content: "\F53E";
+}
+.mdi-truck-delivery-outline::before {
+  content: "\F02C6";
+}
+.mdi-truck-fast::before {
+  content: "\F787";
+}
+.mdi-truck-fast-outline::before {
+  content: "\F02C7";
+}
+.mdi-truck-outline::before {
+  content: "\F02C8";
+}
+.mdi-truck-trailer::before {
+  content: "\F726";
+}
+.mdi-trumpet::before {
+  content: "\F00C1";
+}
+.mdi-tshirt-crew::before {
+  content: "\FA7A";
+}
+.mdi-tshirt-crew-outline::before {
+  content: "\F53F";
+}
+.mdi-tshirt-v::before {
+  content: "\FA7B";
+}
+.mdi-tshirt-v-outline::before {
+  content: "\F540";
+}
+.mdi-tumble-dryer::before {
+  content: "\F916";
+}
+.mdi-tumble-dryer-alert::before {
+  content: "\F01E5";
+}
+.mdi-tumble-dryer-off::before {
+  content: "\F01E6";
+}
+.mdi-tumblr::before {
+  content: "\F541";
+}
+.mdi-tumblr-box::before {
+  content: "\F917";
+}
+.mdi-tumblr-reblog::before {
+  content: "\F542";
+}
+.mdi-tune::before {
+  content: "\F62E";
+}
+.mdi-tune-vertical::before {
+  content: "\F66A";
+}
+.mdi-turnstile::before {
+  content: "\FCB1";
+}
+.mdi-turnstile-outline::before {
+  content: "\FCB2";
+}
+.mdi-turtle::before {
+  content: "\FCB3";
+}
+.mdi-twitch::before {
+  content: "\F543";
+}
+.mdi-twitter::before {
+  content: "\F544";
+}
+.mdi-twitter-box::before {
+  content: "\F545";
+}
+.mdi-twitter-circle::before {
+  content: "\F546";
+}
+.mdi-twitter-retweet::before {
+  content: "\F547";
+}
+.mdi-two-factor-authentication::before {
+  content: "\F9AE";
+}
+.mdi-typewriter::before {
+  content: "\FF4A";
+}
+.mdi-uber::before {
+  content: "\F748";
+}
+.mdi-ubisoft::before {
+  content: "\FBB6";
+}
+.mdi-ubuntu::before {
+  content: "\F548";
+}
+.mdi-ufo::before {
+  content: "\F00EF";
+}
+.mdi-ufo-outline::before {
+  content: "\F00F0";
+}
+.mdi-ultra-high-definition::before {
+  content: "\F7F8";
+}
+.mdi-umbraco::before {
+  content: "\F549";
+}
+.mdi-umbrella::before {
+  content: "\F54A";
+}
+.mdi-umbrella-closed::before {
+  content: "\F9AF";
+}
+.mdi-umbrella-outline::before {
+  content: "\F54B";
+}
+.mdi-undo::before {
+  content: "\F54C";
+}
+.mdi-undo-variant::before {
+  content: "\F54D";
+}
+.mdi-unfold-less-horizontal::before {
+  content: "\F54E";
+}
+.mdi-unfold-less-vertical::before {
+  content: "\F75F";
+}
+.mdi-unfold-more-horizontal::before {
+  content: "\F54F";
+}
+.mdi-unfold-more-vertical::before {
+  content: "\F760";
+}
+.mdi-ungroup::before {
+  content: "\F550";
+}
+.mdi-unicode::before {
+  content: "\FEED";
+}
+.mdi-unity::before {
+  content: "\F6AE";
+}
+.mdi-unreal::before {
+  content: "\F9B0";
+}
+.mdi-untappd::before {
+  content: "\F551";
+}
+.mdi-update::before {
+  content: "\F6AF";
+}
+.mdi-upload::before {
+  content: "\F552";
+}
+.mdi-upload-lock::before {
+  content: "\F039E";
+}
+.mdi-upload-lock-outline::before {
+  content: "\F039F";
+}
+.mdi-upload-multiple::before {
+  content: "\F83C";
+}
+.mdi-upload-network::before {
+  content: "\F6F5";
+}
+.mdi-upload-network-outline::before {
+  content: "\FCB4";
+}
+.mdi-upload-off::before {
+  content: "\F00F1";
+}
+.mdi-upload-off-outline::before {
+  content: "\F00F2";
+}
+.mdi-upload-outline::before {
+  content: "\FE67";
+}
+.mdi-usb::before {
+  content: "\F553";
+}
+.mdi-usb-flash-drive::before {
+  content: "\F02C9";
+}
+.mdi-usb-flash-drive-outline::before {
+  content: "\F02CA";
+}
+.mdi-usb-port::before {
+  content: "\F021B";
+}
+.mdi-valve::before {
+  content: "\F0088";
+}
+.mdi-valve-closed::before {
+  content: "\F0089";
+}
+.mdi-valve-open::before {
+  content: "\F008A";
+}
+.mdi-van-passenger::before {
+  content: "\F7F9";
+}
+.mdi-van-utility::before {
+  content: "\F7FA";
+}
+.mdi-vanish::before {
+  content: "\F7FB";
+}
+.mdi-vanity-light::before {
+  content: "\F020C";
+}
+.mdi-variable::before {
+  content: "\FAE6";
+}
+.mdi-variable-box::before {
+  content: "\F013C";
+}
+.mdi-vector-arrange-above::before {
+  content: "\F554";
+}
+.mdi-vector-arrange-below::before {
+  content: "\F555";
+}
+.mdi-vector-bezier::before {
+  content: "\FAE7";
+}
+.mdi-vector-circle::before {
+  content: "\F556";
+}
+.mdi-vector-circle-variant::before {
+  content: "\F557";
+}
+.mdi-vector-combine::before {
+  content: "\F558";
+}
+.mdi-vector-curve::before {
+  content: "\F559";
+}
+.mdi-vector-difference::before {
+  content: "\F55A";
+}
+.mdi-vector-difference-ab::before {
+  content: "\F55B";
+}
+.mdi-vector-difference-ba::before {
+  content: "\F55C";
+}
+.mdi-vector-ellipse::before {
+  content: "\F892";
+}
+.mdi-vector-intersection::before {
+  content: "\F55D";
+}
+.mdi-vector-line::before {
+  content: "\F55E";
+}
+.mdi-vector-link::before {
+  content: "\F0009";
+}
+.mdi-vector-point::before {
+  content: "\F55F";
+}
+.mdi-vector-polygon::before {
+  content: "\F560";
+}
+.mdi-vector-polyline::before {
+  content: "\F561";
+}
+.mdi-vector-polyline-edit::before {
+  content: "\F0250";
+}
+.mdi-vector-polyline-minus::before {
+  content: "\F0251";
+}
+.mdi-vector-polyline-plus::before {
+  content: "\F0252";
+}
+.mdi-vector-polyline-remove::before {
+  content: "\F0253";
+}
+.mdi-vector-radius::before {
+  content: "\F749";
+}
+.mdi-vector-rectangle::before {
+  content: "\F5C6";
+}
+.mdi-vector-selection::before {
+  content: "\F562";
+}
+.mdi-vector-square::before {
+  content: "\F001";
+}
+.mdi-vector-triangle::before {
+  content: "\F563";
+}
+.mdi-vector-union::before {
+  content: "\F564";
+}
+.mdi-venmo::before {
+  content: "\F578";
+}
+.mdi-vhs::before {
+  content: "\FA1A";
+}
+.mdi-vibrate::before {
+  content: "\F566";
+}
+.mdi-vibrate-off::before {
+  content: "\FCB5";
+}
+.mdi-video::before {
+  content: "\F567";
+}
+.mdi-video-3d::before {
+  content: "\F7FC";
+}
+.mdi-video-3d-variant::before {
+  content: "\FEEE";
+}
+.mdi-video-4k-box::before {
+  content: "\F83D";
+}
+.mdi-video-account::before {
+  content: "\F918";
+}
+.mdi-video-check::before {
+  content: "\F008B";
+}
+.mdi-video-check-outline::before {
+  content: "\F008C";
+}
+.mdi-video-image::before {
+  content: "\F919";
+}
+.mdi-video-input-antenna::before {
+  content: "\F83E";
+}
+.mdi-video-input-component::before {
+  content: "\F83F";
+}
+.mdi-video-input-hdmi::before {
+  content: "\F840";
+}
+.mdi-video-input-scart::before {
+  content: "\FFA9";
+}
+.mdi-video-input-svideo::before {
+  content: "\F841";
+}
+.mdi-video-minus::before {
+  content: "\F9B1";
+}
+.mdi-video-off::before {
+  content: "\F568";
+}
+.mdi-video-off-outline::before {
+  content: "\FBB7";
+}
+.mdi-video-outline::before {
+  content: "\FBB8";
+}
+.mdi-video-plus::before {
+  content: "\F9B2";
+}
+.mdi-video-stabilization::before {
+  content: "\F91A";
+}
+.mdi-video-switch::before {
+  content: "\F569";
+}
+.mdi-video-vintage::before {
+  content: "\FA1B";
+}
+.mdi-video-wireless::before {
+  content: "\FEEF";
+}
+.mdi-video-wireless-outline::before {
+  content: "\FEF0";
+}
+.mdi-view-agenda::before {
+  content: "\F56A";
+}
+.mdi-view-agenda-outline::before {
+  content: "\F0203";
+}
+.mdi-view-array::before {
+  content: "\F56B";
+}
+.mdi-view-carousel::before {
+  content: "\F56C";
+}
+.mdi-view-column::before {
+  content: "\F56D";
+}
+.mdi-view-comfy::before {
+  content: "\FE4D";
+}
+.mdi-view-compact::before {
+  content: "\FE4E";
+}
+.mdi-view-compact-outline::before {
+  content: "\FE4F";
+}
+.mdi-view-dashboard::before {
+  content: "\F56E";
+}
+.mdi-view-dashboard-outline::before {
+  content: "\FA1C";
+}
+.mdi-view-dashboard-variant::before {
+  content: "\F842";
+}
+.mdi-view-day::before {
+  content: "\F56F";
+}
+.mdi-view-grid::before {
+  content: "\F570";
+}
+.mdi-view-grid-outline::before {
+  content: "\F0204";
+}
+.mdi-view-grid-plus::before {
+  content: "\FFAA";
+}
+.mdi-view-grid-plus-outline::before {
+  content: "\F0205";
+}
+.mdi-view-headline::before {
+  content: "\F571";
+}
+.mdi-view-list::before {
+  content: "\F572";
+}
+.mdi-view-module::before {
+  content: "\F573";
+}
+.mdi-view-parallel::before {
+  content: "\F727";
+}
+.mdi-view-quilt::before {
+  content: "\F574";
+}
+.mdi-view-sequential::before {
+  content: "\F728";
+}
+.mdi-view-split-horizontal::before {
+  content: "\FBA7";
+}
+.mdi-view-split-vertical::before {
+  content: "\FBA8";
+}
+.mdi-view-stream::before {
+  content: "\F575";
+}
+.mdi-view-week::before {
+  content: "\F576";
+}
+.mdi-vimeo::before {
+  content: "\F577";
+}
+.mdi-violin::before {
+  content: "\F60F";
+}
+.mdi-virtual-reality::before {
+  content: "\F893";
+}
+.mdi-visual-studio::before {
+  content: "\F610";
+}
+.mdi-visual-studio-code::before {
+  content: "\FA1D";
+}
+.mdi-vk::before {
+  content: "\F579";
+}
+.mdi-vk-box::before {
+  content: "\F57A";
+}
+.mdi-vk-circle::before {
+  content: "\F57B";
+}
+.mdi-vlc::before {
+  content: "\F57C";
+}
+.mdi-voice::before {
+  content: "\F5CB";
+}
+.mdi-voice-off::before {
+  content: "\FEF1";
+}
+.mdi-voicemail::before {
+  content: "\F57D";
+}
+.mdi-volleyball::before {
+  content: "\F9B3";
+}
+.mdi-volume-high::before {
+  content: "\F57E";
+}
+.mdi-volume-low::before {
+  content: "\F57F";
+}
+.mdi-volume-medium::before {
+  content: "\F580";
+}
+.mdi-volume-minus::before {
+  content: "\F75D";
+}
+.mdi-volume-mute::before {
+  content: "\F75E";
+}
+.mdi-volume-off::before {
+  content: "\F581";
+}
+.mdi-volume-plus::before {
+  content: "\F75C";
+}
+.mdi-volume-source::before {
+  content: "\F014B";
+}
+.mdi-volume-variant-off::before {
+  content: "\FE68";
+}
+.mdi-volume-vibrate::before {
+  content: "\F014C";
+}
+.mdi-vote::before {
+  content: "\FA1E";
+}
+.mdi-vote-outline::before {
+  content: "\FA1F";
+}
+.mdi-vpn::before {
+  content: "\F582";
+}
+.mdi-vuejs::before {
+  content: "\F843";
+}
+.mdi-vuetify::before {
+  content: "\FE50";
+}
+.mdi-walk::before {
+  content: "\F583";
+}
+.mdi-wall::before {
+  content: "\F7FD";
+}
+.mdi-wall-sconce::before {
+  content: "\F91B";
+}
+.mdi-wall-sconce-flat::before {
+  content: "\F91C";
+}
+.mdi-wall-sconce-variant::before {
+  content: "\F91D";
+}
+.mdi-wallet::before {
+  content: "\F584";
+}
+.mdi-wallet-giftcard::before {
+  content: "\F585";
+}
+.mdi-wallet-membership::before {
+  content: "\F586";
+}
+.mdi-wallet-outline::before {
+  content: "\FBB9";
+}
+.mdi-wallet-plus::before {
+  content: "\FFAB";
+}
+.mdi-wallet-plus-outline::before {
+  content: "\FFAC";
+}
+.mdi-wallet-travel::before {
+  content: "\F587";
+}
+.mdi-wallpaper::before {
+  content: "\FE69";
+}
+.mdi-wan::before {
+  content: "\F588";
+}
+.mdi-wardrobe::before {
+  content: "\FFAD";
+}
+.mdi-wardrobe-outline::before {
+  content: "\FFAE";
+}
+.mdi-warehouse::before {
+  content: "\FFBB";
+}
+.mdi-washing-machine::before {
+  content: "\F729";
+}
+.mdi-washing-machine-alert::before {
+  content: "\F01E7";
+}
+.mdi-washing-machine-off::before {
+  content: "\F01E8";
+}
+.mdi-watch::before {
+  content: "\F589";
+}
+.mdi-watch-export::before {
+  content: "\F58A";
+}
+.mdi-watch-export-variant::before {
+  content: "\F894";
+}
+.mdi-watch-import::before {
+  content: "\F58B";
+}
+.mdi-watch-import-variant::before {
+  content: "\F895";
+}
+.mdi-watch-variant::before {
+  content: "\F896";
+}
+.mdi-watch-vibrate::before {
+  content: "\F6B0";
+}
+.mdi-watch-vibrate-off::before {
+  content: "\FCB6";
+}
+.mdi-water::before {
+  content: "\F58C";
+}
+.mdi-water-boiler::before {
+  content: "\FFAF";
+}
+.mdi-water-boiler-alert::before {
+  content: "\F01DE";
+}
+.mdi-water-boiler-off::before {
+  content: "\F01DF";
+}
+.mdi-water-off::before {
+  content: "\F58D";
+}
+.mdi-water-outline::before {
+  content: "\FE6A";
+}
+.mdi-water-percent::before {
+  content: "\F58E";
+}
+.mdi-water-polo::before {
+  content: "\F02CB";
+}
+.mdi-water-pump::before {
+  content: "\F58F";
+}
+.mdi-water-pump-off::before {
+  content: "\FFB0";
+}
+.mdi-water-well::before {
+  content: "\F008D";
+}
+.mdi-water-well-outline::before {
+  content: "\F008E";
+}
+.mdi-watermark::before {
+  content: "\F612";
+}
+.mdi-wave::before {
+  content: "\FF4B";
+}
+.mdi-waves::before {
+  content: "\F78C";
+}
+.mdi-waze::before {
+  content: "\FBBA";
+}
+.mdi-weather-cloudy::before {
+  content: "\F590";
+}
+.mdi-weather-cloudy-alert::before {
+  content: "\FF4C";
+}
+.mdi-weather-cloudy-arrow-right::before {
+  content: "\FE51";
+}
+.mdi-weather-fog::before {
+  content: "\F591";
+}
+.mdi-weather-hail::before {
+  content: "\F592";
+}
+.mdi-weather-hazy::before {
+  content: "\FF4D";
+}
+.mdi-weather-hurricane::before {
+  content: "\F897";
+}
+.mdi-weather-lightning::before {
+  content: "\F593";
+}
+.mdi-weather-lightning-rainy::before {
+  content: "\F67D";
+}
+.mdi-weather-night::before {
+  content: "\F594";
+}
+.mdi-weather-night-partly-cloudy::before {
+  content: "\FF4E";
+}
+.mdi-weather-partly-cloudy::before {
+  content: "\F595";
+}
+.mdi-weather-partly-lightning::before {
+  content: "\FF4F";
+}
+.mdi-weather-partly-rainy::before {
+  content: "\FF50";
+}
+.mdi-weather-partly-snowy::before {
+  content: "\FF51";
+}
+.mdi-weather-partly-snowy-rainy::before {
+  content: "\FF52";
+}
+.mdi-weather-pouring::before {
+  content: "\F596";
+}
+.mdi-weather-rainy::before {
+  content: "\F597";
+}
+.mdi-weather-snowy::before {
+  content: "\F598";
+}
+.mdi-weather-snowy-heavy::before {
+  content: "\FF53";
+}
+.mdi-weather-snowy-rainy::before {
+  content: "\F67E";
+}
+.mdi-weather-sunny::before {
+  content: "\F599";
+}
+.mdi-weather-sunny-alert::before {
+  content: "\FF54";
+}
+.mdi-weather-sunset::before {
+  content: "\F59A";
+}
+.mdi-weather-sunset-down::before {
+  content: "\F59B";
+}
+.mdi-weather-sunset-up::before {
+  content: "\F59C";
+}
+.mdi-weather-tornado::before {
+  content: "\FF55";
+}
+.mdi-weather-windy::before {
+  content: "\F59D";
+}
+.mdi-weather-windy-variant::before {
+  content: "\F59E";
+}
+.mdi-web::before {
+  content: "\F59F";
+}
+.mdi-web-box::before {
+  content: "\FFB1";
+}
+.mdi-web-clock::before {
+  content: "\F0275";
+}
+.mdi-webcam::before {
+  content: "\F5A0";
+}
+.mdi-webhook::before {
+  content: "\F62F";
+}
+.mdi-webpack::before {
+  content: "\F72A";
+}
+.mdi-webrtc::before {
+  content: "\F0273";
+}
+.mdi-wechat::before {
+  content: "\F611";
+}
+.mdi-weight::before {
+  content: "\F5A1";
+}
+.mdi-weight-gram::before {
+  content: "\FD1B";
+}
+.mdi-weight-kilogram::before {
+  content: "\F5A2";
+}
+.mdi-weight-lifter::before {
+  content: "\F0188";
+}
+.mdi-weight-pound::before {
+  content: "\F9B4";
+}
+.mdi-whatsapp::before {
+  content: "\F5A3";
+}
+.mdi-wheelchair-accessibility::before {
+  content: "\F5A4";
+}
+.mdi-whistle::before {
+  content: "\F9B5";
+}
+.mdi-whistle-outline::before {
+  content: "\F02E7";
+}
+.mdi-white-balance-auto::before {
+  content: "\F5A5";
+}
+.mdi-white-balance-incandescent::before {
+  content: "\F5A6";
+}
+.mdi-white-balance-iridescent::before {
+  content: "\F5A7";
+}
+.mdi-white-balance-sunny::before {
+  content: "\F5A8";
+}
+.mdi-widgets::before {
+  content: "\F72B";
+}
+.mdi-widgets-outline::before {
+  content: "\F0380";
+}
+.mdi-wifi::before {
+  content: "\F5A9";
+}
+.mdi-wifi-off::before {
+  content: "\F5AA";
+}
+.mdi-wifi-star::before {
+  content: "\FE6B";
+}
+.mdi-wifi-strength-1::before {
+  content: "\F91E";
+}
+.mdi-wifi-strength-1-alert::before {
+  content: "\F91F";
+}
+.mdi-wifi-strength-1-lock::before {
+  content: "\F920";
+}
+.mdi-wifi-strength-2::before {
+  content: "\F921";
+}
+.mdi-wifi-strength-2-alert::before {
+  content: "\F922";
+}
+.mdi-wifi-strength-2-lock::before {
+  content: "\F923";
+}
+.mdi-wifi-strength-3::before {
+  content: "\F924";
+}
+.mdi-wifi-strength-3-alert::before {
+  content: "\F925";
+}
+.mdi-wifi-strength-3-lock::before {
+  content: "\F926";
+}
+.mdi-wifi-strength-4::before {
+  content: "\F927";
+}
+.mdi-wifi-strength-4-alert::before {
+  content: "\F928";
+}
+.mdi-wifi-strength-4-lock::before {
+  content: "\F929";
+}
+.mdi-wifi-strength-alert-outline::before {
+  content: "\F92A";
+}
+.mdi-wifi-strength-lock-outline::before {
+  content: "\F92B";
+}
+.mdi-wifi-strength-off::before {
+  content: "\F92C";
+}
+.mdi-wifi-strength-off-outline::before {
+  content: "\F92D";
+}
+.mdi-wifi-strength-outline::before {
+  content: "\F92E";
+}
+.mdi-wii::before {
+  content: "\F5AB";
+}
+.mdi-wiiu::before {
+  content: "\F72C";
+}
+.mdi-wikipedia::before {
+  content: "\F5AC";
+}
+.mdi-wind-turbine::before {
+  content: "\FD81";
+}
+.mdi-window-close::before {
+  content: "\F5AD";
+}
+.mdi-window-closed::before {
+  content: "\F5AE";
+}
+.mdi-window-closed-variant::before {
+  content: "\F0206";
+}
+.mdi-window-maximize::before {
+  content: "\F5AF";
+}
+.mdi-window-minimize::before {
+  content: "\F5B0";
+}
+.mdi-window-open::before {
+  content: "\F5B1";
+}
+.mdi-window-open-variant::before {
+  content: "\F0207";
+}
+.mdi-window-restore::before {
+  content: "\F5B2";
+}
+.mdi-window-shutter::before {
+  content: "\F0147";
+}
+.mdi-window-shutter-alert::before {
+  content: "\F0148";
+}
+.mdi-window-shutter-open::before {
+  content: "\F0149";
+}
+.mdi-windows::before {
+  content: "\F5B3";
+}
+.mdi-windows-classic::before {
+  content: "\FA20";
+}
+.mdi-wiper::before {
+  content: "\FAE8";
+}
+.mdi-wiper-wash::before {
+  content: "\FD82";
+}
+.mdi-wordpress::before {
+  content: "\F5B4";
+}
+.mdi-worker::before {
+  content: "\F5B5";
+}
+.mdi-wrap::before {
+  content: "\F5B6";
+}
+.mdi-wrap-disabled::before {
+  content: "\FBBB";
+}
+.mdi-wrench::before {
+  content: "\F5B7";
+}
+.mdi-wrench-outline::before {
+  content: "\FBBC";
+}
+.mdi-wunderlist::before {
+  content: "\F5B8";
+}
+.mdi-xamarin::before {
+  content: "\F844";
+}
+.mdi-xamarin-outline::before {
+  content: "\F845";
+}
+.mdi-xaml::before {
+  content: "\F673";
+}
+.mdi-xbox::before {
+  content: "\F5B9";
+}
+.mdi-xbox-controller::before {
+  content: "\F5BA";
+}
+.mdi-xbox-controller-battery-alert::before {
+  content: "\F74A";
+}
+.mdi-xbox-controller-battery-charging::before {
+  content: "\FA21";
+}
+.mdi-xbox-controller-battery-empty::before {
+  content: "\F74B";
+}
+.mdi-xbox-controller-battery-full::before {
+  content: "\F74C";
+}
+.mdi-xbox-controller-battery-low::before {
+  content: "\F74D";
+}
+.mdi-xbox-controller-battery-medium::before {
+  content: "\F74E";
+}
+.mdi-xbox-controller-battery-unknown::before {
+  content: "\F74F";
+}
+.mdi-xbox-controller-menu::before {
+  content: "\FE52";
+}
+.mdi-xbox-controller-off::before {
+  content: "\F5BB";
+}
+.mdi-xbox-controller-view::before {
+  content: "\FE53";
+}
+.mdi-xda::before {
+  content: "\F5BC";
+}
+.mdi-xing::before {
+  content: "\F5BD";
+}
+.mdi-xing-box::before {
+  content: "\F5BE";
+}
+.mdi-xing-circle::before {
+  content: "\F5BF";
+}
+.mdi-xml::before {
+  content: "\F5C0";
+}
+.mdi-xmpp::before {
+  content: "\F7FE";
+}
+.mdi-yahoo::before {
+  content: "\FB2A";
+}
+.mdi-yammer::before {
+  content: "\F788";
+}
+.mdi-yeast::before {
+  content: "\F5C1";
+}
+.mdi-yelp::before {
+  content: "\F5C2";
+}
+.mdi-yin-yang::before {
+  content: "\F67F";
+}
+.mdi-yoga::before {
+  content: "\F01A7";
+}
+.mdi-youtube::before {
+  content: "\F5C3";
+}
+.mdi-youtube-creator-studio::before {
+  content: "\F846";
+}
+.mdi-youtube-gaming::before {
+  content: "\F847";
+}
+.mdi-youtube-subscription::before {
+  content: "\FD1C";
+}
+.mdi-youtube-tv::before {
+  content: "\F448";
+}
+.mdi-z-wave::before {
+  content: "\FAE9";
+}
+.mdi-zend::before {
+  content: "\FAEA";
+}
+.mdi-zigbee::before {
+  content: "\FD1D";
+}
+.mdi-zip-box::before {
+  content: "\F5C4";
+}
+.mdi-zip-box-outline::before {
+  content: "\F001B";
+}
+.mdi-zip-disk::before {
+  content: "\FA22";
+}
+.mdi-zodiac-aquarius::before {
+  content: "\FA7C";
+}
+.mdi-zodiac-aries::before {
+  content: "\FA7D";
+}
+.mdi-zodiac-cancer::before {
+  content: "\FA7E";
+}
+.mdi-zodiac-capricorn::before {
+  content: "\FA7F";
+}
+.mdi-zodiac-gemini::before {
+  content: "\FA80";
+}
+.mdi-zodiac-leo::before {
+  content: "\FA81";
+}
+.mdi-zodiac-libra::before {
+  content: "\FA82";
+}
+.mdi-zodiac-pisces::before {
+  content: "\FA83";
+}
+.mdi-zodiac-sagittarius::before {
+  content: "\FA84";
+}
+.mdi-zodiac-scorpio::before {
+  content: "\FA85";
+}
+.mdi-zodiac-taurus::before {
+  content: "\FA86";
+}
+.mdi-zodiac-virgo::before {
+  content: "\FA87";
+}
+.mdi-blank::before {
+  content: "\F68C";
+  visibility: hidden;
+}
+.mdi-18px.mdi-set,
+.mdi-18px.mdi:before {
+  font-size: 18px;
+}
+.mdi-24px.mdi-set,
+.mdi-24px.mdi:before {
+  font-size: 24px;
+}
+.mdi-36px.mdi-set,
+.mdi-36px.mdi:before {
+  font-size: 36px;
+}
+.mdi-48px.mdi-set,
+.mdi-48px.mdi:before {
+  font-size: 48px;
+}
+.mdi-dark:before {
+  color: rgba(0, 0, 0, 0.54);
+}
+.mdi-dark.mdi-inactive:before {
+  color: rgba(0, 0, 0, 0.26);
+}
+.mdi-light:before {
+  color: #fff;
+}
+.mdi-light.mdi-inactive:before {
+  color: rgba(255, 255, 255, 0.3);
+}
+.mdi-rotate-45:before {
+  -webkit-transform: rotate(45deg);
+  -ms-transform: rotate(45deg);
+  transform: rotate(45deg);
+}
+.mdi-rotate-90:before {
+  -webkit-transform: rotate(90deg);
+  -ms-transform: rotate(90deg);
+  transform: rotate(90deg);
+}
+.mdi-rotate-135:before {
+  -webkit-transform: rotate(135deg);
+  -ms-transform: rotate(135deg);
+  transform: rotate(135deg);
+}
+.mdi-rotate-180:before {
+  -webkit-transform: rotate(180deg);
+  -ms-transform: rotate(180deg);
+  transform: rotate(180deg);
+}
+.mdi-rotate-225:before {
+  -webkit-transform: rotate(225deg);
+  -ms-transform: rotate(225deg);
+  transform: rotate(225deg);
+}
+.mdi-rotate-270:before {
+  -webkit-transform: rotate(270deg);
+  -ms-transform: rotate(270deg);
+  transform: rotate(270deg);
+}
+.mdi-rotate-315:before {
+  -webkit-transform: rotate(315deg);
+  -ms-transform: rotate(315deg);
+  transform: rotate(315deg);
+}
+.mdi-flip-h:before {
+  -webkit-transform: scaleX(-1);
+  transform: scaleX(-1);
+  filter: FlipH;
+  -ms-filter: "FlipH";
+}
+.mdi-flip-v:before {
+  -webkit-transform: scaleY(-1);
+  transform: scaleY(-1);
+  filter: FlipV;
+  -ms-filter: "FlipV";
+}
+.mdi-spin:before {
+  -webkit-animation: mdi-spin 2s infinite linear;
+  animation: mdi-spin 2s infinite linear;
+}
+@-webkit-keyframes mdi-spin {
+  0% {
+    -webkit-transform: rotate(0deg);
+    transform: rotate(0deg);
+  }
+  100% {
+    -webkit-transform: rotate(359deg);
+    transform: rotate(359deg);
+  }
+}
+@keyframes mdi-spin {
+  0% {
+    -webkit-transform: rotate(0deg);
+    transform: rotate(0deg);
+  }
+  100% {
+    -webkit-transform: rotate(359deg);
+    transform: rotate(359deg);
+  }
+}
+
+/*# sourceMappingURL=materialdesignicons.css.map */
diff --git a/packages/auditor-backoffice-ui/src/scss/libs/_all.scss 
b/packages/auditor-backoffice-ui/src/scss/libs/_all.scss
new file mode 100644
index 000000000..cba6f26eb
--- /dev/null
+++ b/packages/auditor-backoffice-ui/src/scss/libs/_all.scss
@@ -0,0 +1,29 @@
+/*
+ This file is part of GNU Taler
+ (C) 2021-2023 Taler Systems S.A.
+
+ GNU Taler is free software; you can redistribute it and/or modify it under the
+ terms of the GNU General Public License as published by the Free Software
+ Foundation; either version 3, or (at your option) any later version.
+
+ GNU Taler is distributed in the hope that it will be useful, but WITHOUT ANY
+ WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
+ A PARTICULAR PURPOSE.  See the GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License along with
+ GNU Taler; see the file COPYING.  If not, see <http://www.gnu.org/licenses/>
+ */
+
+/**
+ *
+ * @author Sebastian Javier Marchano (sebasjm)
+ */
+
+@import "node_modules/bulma-radio/bulma-radio";
+// @import "node_modules/bulma-responsive-tables/bulma-responsive-tables";
+@import "node_modules/bulma-checkbox/bulma-checkbox";
+@import "node_modules/bulma-switch-control/bulma-switch-control";
+@import "node_modules/bulma-upload-control/bulma-upload-control";
+
+/* Bulma */
+@import "node_modules/bulma/bulma";
diff --git a/packages/auditor-backoffice-ui/src/scss/main.scss 
b/packages/auditor-backoffice-ui/src/scss/main.scss
new file mode 100644
index 000000000..c4be8aa73
--- /dev/null
+++ b/packages/auditor-backoffice-ui/src/scss/main.scss
@@ -0,0 +1,195 @@
+/*
+ This file is part of GNU Taler
+ (C) 2021-2023 Taler Systems S.A.
+
+ GNU Taler is free software; you can redistribute it and/or modify it under the
+ terms of the GNU General Public License as published by the Free Software
+ Foundation; either version 3, or (at your option) any later version.
+ 
+ GNU Taler is distributed in the hope that it will be useful, but WITHOUT ANY
+ WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
+ A PARTICULAR PURPOSE.  See the GNU General Public License for more details.
+ 
+ You should have received a copy of the GNU General Public License along with
+ GNU Taler; see the file COPYING.  If not, see <http://www.gnu.org/licenses/>
+ */
+
+/**
+ *
+ * @author Sebastian Javier Marchano (sebasjm)
+ */
+
+/* Theme style (colors & sizes) */
+@import "theme-default";
+
+/* Core Libs & Lib configs */
+@import "libs/all";
+
+/* Mixins */
+@import "mixins";
+
+/* Theme components */
+@import "nav-bar";
+@import "aside";
+@import "title-bar";
+@import "hero-bar";
+@import "card";
+@import "table";
+@import "tiles";
+@import "form";
+@import "main-section";
+@import "modal";
+@import "footer";
+@import "misc";
+@import "custom-calendar";
+@import "loading";
+
+@import "fonts/nunito.css";
+@import "icons/materialdesignicons-4.9.95.min.css";
+
+$tooltip-color: red;
+
+@import 
"../../node_modules/@creativebulma/bulma-tooltip/dist/bulma-tooltip.min.css";
+@import "../../node_modules/bulma-timeline/dist/css/bulma-timeline.min.css";
+
+@import "toggle";
+
+.notification {
+  background-color: transparent;
+}
+
+.timeline .timeline-item .timeline-content {
+  padding-top: 0;
+}
+
+.timeline .timeline-item:last-child::before {
+  display: none;
+}
+
+.timeline .timeline-item .timeline-marker {
+  top: 0;
+}
+
+.toast {
+  position: absolute;
+  width: 60%;
+  margin-left: 10%;
+  margin-right: 10%;
+  z-index: 999;
+
+  display: flex;
+  flex-direction: column;
+  padding: 15px;
+  text-align: center;
+  pointer-events: none;
+}
+
+.toast>.message {
+  white-space: pre-wrap;
+  opacity: 80%;
+}
+
+div {
+  &.is-loading {
+    position: relative;
+    pointer-events: none;
+    opacity: 0.5;
+
+    &:after {
+      // @include loader;
+      position: absolute;
+      top: calc(50% - 2.5em);
+      left: calc(50% - 2.5em);
+      width: 5em;
+      height: 5em;
+      border-width: 0.25em;
+    }
+  }
+}
+
+input[type="checkbox"]:indeterminate+.check {
+  background: red !important;
+}
+
+.right-sticky {
+  position: sticky;
+  right: 0px;
+  background-color: $white;
+}
+
+.right-sticky .buttons {
+  flex-wrap: nowrap;
+}
+
+.table.is-striped tbody tr:not(.is-selected):nth-child(even) .right-sticky {
+  background-color: #fafafa;
+}
+
+tr:hover .right-sticky {
+  background-color: hsl(0, 0%, 80%);
+}
+
+.table.is-striped tbody tr:nth-child(even):hover .right-sticky {
+  background-color: hsl(0, 0%, 95%);
+}
+
+.content-full-size {
+  height: calc(100% - 3rem);
+  position: absolute;
+  width: calc(100% - 14rem);
+  display: flex;
+}
+
+.content-full-size .column .card {
+  min-width: 200px;
+}
+
+@include touch {
+  .content-full-size {
+    height: 100%;
+    position: absolute;
+    width: 100%;
+  }
+}
+
+.column.is-half {
+  flex: none;
+  width: 50%;
+}
+
+input:read-only {
+  cursor: initial;
+}
+
+[data-tooltip]:before {
+  max-width: 15rem;
+  width: max-content;
+  text-align: left;
+  transition: opacity 0.1s linear 1s;
+  // transform: inherit !important;
+  white-space: pre-wrap !important;
+  font-weight: normal;
+  // position: relative;
+}
+
+.icon[data-tooltip]:before {
+  transition: none;
+  z-index: 5;
+}
+
+span[data-tooltip] {
+  border-bottom: none;
+}
+
+div[data-tooltip]::before {
+  position: absolute;
+}
+
+.modal-card-body>p {
+  padding: 1em;
+}
+
+.modal-card-body>p.warning {
+  background-color: #fffbdd;
+  border: solid 1px #f2e9bf;
+}
\ No newline at end of file
diff --git a/packages/auditor-backoffice-ui/src/scss/toggle.scss 
b/packages/auditor-backoffice-ui/src/scss/toggle.scss
new file mode 100644
index 000000000..24636da2f
--- /dev/null
+++ b/packages/auditor-backoffice-ui/src/scss/toggle.scss
@@ -0,0 +1,51 @@
+$green: #56c080;
+
+.toggle {
+  cursor: pointer;
+  display: inline-block;
+}
+.toggle-switch {
+  display: inline-block;
+  background: #ccc;
+  border-radius: 16px;
+  width: 58px;
+  height: 32px;
+  position: relative;
+  vertical-align: middle;
+  transition: background 0.25s;
+  &:before,
+  &:after {
+    content: "";
+  }
+  &:before {
+    display: block;
+    background: linear-gradient(to bottom, #fff 0%, #eee 100%);
+    border-radius: 50%;
+    box-shadow: 0 0 0 1px rgba(0, 0, 0, 0.25);
+    width: 24px;
+    height: 24px;
+    position: absolute;
+    top: 4px;
+    left: 4px;
+    transition: left 0.25s;
+  }
+  .toggle:hover &:before {
+    background: linear-gradient(to bottom, #fff 0%, #fff 100%);
+    box-shadow: 0 0 0 1px rgba(0, 0, 0, 0.5);
+  }
+  .toggle-checkbox:checked + & {
+    background: $green;
+    &:before {
+      left: 30px;
+    }
+  }
+}
+.toggle-checkbox {
+  position: absolute;
+  visibility: hidden;
+}
+.toggle-label {
+  margin-left: 5px;
+  position: relative;
+  top: 2px;
+}
diff --git a/packages/auditor-backoffice-ui/src/stories.test.ts 
b/packages/auditor-backoffice-ui/src/stories.test.ts
new file mode 100644
index 000000000..abd993550
--- /dev/null
+++ b/packages/auditor-backoffice-ui/src/stories.test.ts
@@ -0,0 +1,44 @@
+/*
+ This file is part of GNU Taler
+ (C) 2021-2023 Taler Systems S.A.
+
+ GNU Taler is free software; you can redistribute it and/or modify it under the
+ terms of the GNU General Public License as published by the Free Software
+ Foundation; either version 3, or (at your option) any later version.
+
+ GNU Taler is distributed in the hope that it will be useful, but WITHOUT ANY
+ WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
+ A PARTICULAR PURPOSE.  See the GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License along with
+ GNU Taler; see the file COPYING.  If not, see <http://www.gnu.org/licenses/>
+ */
+
+/**
+ *
+ * @author Sebastian Javier Marchano (sebasjm)
+ */
+import { setupI18n } from "@gnu-taler/taler-util";
+import * as tests from "@gnu-taler/web-util/testing";
+import { parseGroupImport } from "@gnu-taler/web-util/browser";
+import * as admin from "./paths/admin/index.stories.js";
+import * as instance from "./paths/instance/index.stories.js";
+
+setupI18n("en", { en: {} });
+
+describe("All the examples:", () => {
+  const cms = parseGroupImport({ admin, instance });
+  cms.forEach((group) => {
+    describe(`Example for group: ${group.title}`, () => {
+      group.list.forEach((component) => {
+        describe(`Component: ${component.name}`, () => {
+          component.examples.forEach((example) => {
+            it(`should render example: ${example.name}`, () => {
+              tests.renderUI(example.render);
+            });
+          });
+        });
+      });
+    });
+  });
+});
diff --git a/packages/auditor-backoffice-ui/src/stories.tsx 
b/packages/auditor-backoffice-ui/src/stories.tsx
new file mode 100644
index 000000000..8bb06b8cb
--- /dev/null
+++ b/packages/auditor-backoffice-ui/src/stories.tsx
@@ -0,0 +1,48 @@
+/*
+ This file is part of GNU Taler
+ (C) 2021-2024 Taler Systems S.A.
+
+ GNU Taler is free software; you can redistribute it and/or modify it under the
+ terms of the GNU General Public License as published by the Free Software
+ Foundation; either version 3, or (at your option) any later version.
+
+ GNU Taler is distributed in the hope that it will be useful, but WITHOUT ANY
+ WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
+ A PARTICULAR PURPOSE.  See the GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License along with
+ GNU Taler; see the file COPYING.  If not, see <http://www.gnu.org/licenses/>
+ */
+
+/**
+ *
+ * @author Sebastian Javier Marchano (sebasjm)
+ */
+import { strings } from "./i18n/strings.js";
+
+import * as admin from "./paths/admin/index.stories.js";
+import * as instance from "./paths/instance/index.stories.js";
+import * as components from "./components/index.stories.js";
+
+import { renderStories } from "@gnu-taler/web-util/browser";
+
+import "./scss/main.scss";
+
+function SortStories(a: any, b: any): number {
+  return (a?.order ?? 0) - (b?.order ?? 0);
+}
+
+function main(): void {
+  renderStories(
+    { admin, instance, components },
+    {
+      strings,
+    },
+  );
+}
+
+if (document.readyState === "loading") {
+  document.addEventListener("DOMContentLoaded", main);
+} else {
+  main();
+}
diff --git a/packages/auditor-backoffice-ui/src/sw.js 
b/packages/auditor-backoffice-ui/src/sw.js
new file mode 100644
index 000000000..bf52db6fa
--- /dev/null
+++ b/packages/auditor-backoffice-ui/src/sw.js
@@ -0,0 +1,25 @@
+/*
+ This file is part of GNU Taler
+ (C) 2021-2024 Taler Systems S.A.
+
+ GNU Taler is free software; you can redistribute it and/or modify it under the
+ terms of the GNU General Public License as published by the Free Software
+ Foundation; either version 3, or (at your option) any later version.
+
+ GNU Taler is distributed in the hope that it will be useful, but WITHOUT ANY
+ WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
+ A PARTICULAR PURPOSE.  See the GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License along with
+ GNU Taler; see the file COPYING.  If not, see <http://www.gnu.org/licenses/>
+ */
+
+/**
+ *
+ * @author Sebastian Javier Marchano (sebasjm)
+ */
+
+// import { getFiles, setupPrecaching, setupRouting } from 'preact-cli/sw/';
+
+// setupRouting();
+// setupPrecaching(getFiles());
diff --git a/packages/auditor-backoffice-ui/src/utils/amount.ts 
b/packages/auditor-backoffice-ui/src/utils/amount.ts
new file mode 100644
index 000000000..475489d3e
--- /dev/null
+++ b/packages/auditor-backoffice-ui/src/utils/amount.ts
@@ -0,0 +1,71 @@
+/*
+ This file is part of GNU Taler
+ (C) 2021-2023 Taler Systems S.A.
+
+ GNU Taler is free software; you can redistribute it and/or modify it under the
+ terms of the GNU General Public License as published by the Free Software
+ Foundation; either version 3, or (at your option) any later version.
+
+ GNU Taler is distributed in the hope that it will be useful, but WITHOUT ANY
+ WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
+ A PARTICULAR PURPOSE.  See the GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License along with
+ GNU Taler; see the file COPYING.  If not, see <http://www.gnu.org/licenses/>
+ */
+import {
+  amountFractionalBase,
+  AmountJson,
+  Amounts,
+} from "@gnu-taler/taler-util";
+import { MerchantBackend } from "../declaration.js";
+
+/**
+ * merge refund with the same description and a difference less than one minute
+ * @param prev list of refunds that will hold the merged refunds
+ * @param cur new refund to add to the list
+ * @returns list with the new refund, may be merged with the last
+ */
+export function mergeRefunds(
+  prev: MerchantBackend.Orders.RefundDetails[],
+  cur: MerchantBackend.Orders.RefundDetails,
+): MerchantBackend.Orders.RefundDetails[] {
+  let tail;
+
+  if (
+    prev.length === 0 || //empty list
+    cur.timestamp.t_s === "never" || //current does not have timestamp
+    (tail = prev[prev.length - 1]).timestamp.t_s === "never" || // last does 
not have timestamp
+    cur.reason !== tail.reason || //different reason
+    cur.pending !== tail.pending || //different pending state
+    Math.abs(cur.timestamp.t_s - tail.timestamp.t_s) > 1000 * 60
+  ) {
+    //more than 1 minute difference
+
+    //can't merge refunds, they are different or to distant in time
+    prev.push(cur);
+    return prev;
+  }
+
+  const a = Amounts.parseOrThrow(tail.amount);
+  const b = Amounts.parseOrThrow(cur.amount);
+  const r = Amounts.add(a, b).amount;
+
+  prev[prev.length - 1] = {
+    ...tail,
+    amount: Amounts.stringify(r),
+  };
+
+  return prev;
+}
+
+export function rate(a: AmountJson, b: AmountJson): number {
+  const af = toFloat(a);
+  const bf = toFloat(b);
+  if (bf === 0) return 0;
+  return af / bf;
+}
+
+function toFloat(amount: AmountJson): number {
+  return amount.value + amount.fraction / amountFractionalBase;
+}
diff --git a/packages/auditor-backoffice-ui/src/utils/constants.ts 
b/packages/auditor-backoffice-ui/src/utils/constants.ts
new file mode 100644
index 000000000..7c4e288b3
--- /dev/null
+++ b/packages/auditor-backoffice-ui/src/utils/constants.ts
@@ -0,0 +1,197 @@
+/*
+ This file is part of GNU Taler
+ (C) 2021-2023 Taler Systems S.A.
+
+ GNU Taler is free software; you can redistribute it and/or modify it under the
+ terms of the GNU General Public License as published by the Free Software
+ Foundation; either version 3, or (at your option) any later version.
+
+ GNU Taler is distributed in the hope that it will be useful, but WITHOUT ANY
+ WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
+ A PARTICULAR PURPOSE.  See the GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License along with
+ GNU Taler; see the file COPYING.  If not, see <http://www.gnu.org/licenses/>
+ */
+
+/**
+ *
+ * @author Sebastian Javier Marchano (sebasjm)
+ */
+
+//https://tools.ietf.org/html/rfc8905
+export const PAYTO_REGEX =
+  
/^payto:\/\/[a-zA-Z][a-zA-Z0-9-.]+(\/[a-zA-Z0-9\-\.\~\(\)@_%:!$&'*+,;=]*)*\??((amount|receiver-name|sender-name|instruction|message)=[a-zA-Z0-9\-\.\~\(\)@_%:!$'*+,;=]*&?)*$/;
+export const PAYTO_WIRE_METHOD_LOOKUP =
+  /payto:\/\/([a-zA-Z][a-zA-Z0-9-.]+)\/.*/;
+
+export const AMOUNT_REGEX = /^[a-zA-Z][a-zA-Z]{1,11}:[0-9][0-9,]*\.?[0-9,]*$/;
+
+export const INSTANCE_ID_LOOKUP = /\/instances\/([^/]*)\/?$/;
+
+export const AMOUNT_ZERO_REGEX = /^[a-zA-Z][a-zA-Z]*:0$/;
+
+export const CROCKFORD_BASE32_REGEX =
+  /^[0123456789ABCDEFGHJKMNPQRSTVWXYZ]+[*~$=U]*$/;
+
+export const URL_REGEX =
+  /^((https?:)(\/\/\/?)([\w]*(?::[\w]*)?@)?([\d\w\.-]+)(?::(\d+))?)\/$/;
+
+// how much rows we add every time user hit load more
+export const PAGE_SIZE = 20;
+// how bigger can be the result set
+// after this threshold, load more with move the cursor
+export const MAX_RESULT_SIZE = PAGE_SIZE * 2 - 1;
+
+// how much we will wait for all request, in seconds
+export const DEFAULT_REQUEST_TIMEOUT = 10;
+
+export const MAX_IMAGE_SIZE = 1024 * 1024;
+
+export const INSTANCE_ID_REGEX = /^[a-zA-Z0-9][a-zA-Z0-9_.@-]+$/;
+
+export const COUNTRY_TABLE = {
+  AE: "U.A.E.",
+  AF: "Afghanistan",
+  AL: "Albania",
+  AM: "Armenia",
+  AN: "Netherlands Antilles",
+  AR: "Argentina",
+  AT: "Austria",
+  AU: "Australia",
+  AZ: "Azerbaijan",
+  BA: "Bosnia and Herzegovina",
+  BD: "Bangladesh",
+  BE: "Belgium",
+  BG: "Bulgaria",
+  BH: "Bahrain",
+  BN: "Brunei Darussalam",
+  BO: "Bolivia",
+  BR: "Brazil",
+  BT: "Bhutan",
+  BY: "Belarus",
+  BZ: "Belize",
+  CA: "Canada",
+  CG: "Congo",
+  CH: "Switzerland",
+  CI: "Cote d'Ivoire",
+  CL: "Chile",
+  CM: "Cameroon",
+  CN: "People's Republic of China",
+  CO: "Colombia",
+  CR: "Costa Rica",
+  CS: "Serbia and Montenegro",
+  CZ: "Czech Republic",
+  DE: "Germany",
+  DK: "Denmark",
+  DO: "Dominican Republic",
+  DZ: "Algeria",
+  EC: "Ecuador",
+  EE: "Estonia",
+  EG: "Egypt",
+  ER: "Eritrea",
+  ES: "Spain",
+  ET: "Ethiopia",
+  FI: "Finland",
+  FO: "Faroe Islands",
+  FR: "France",
+  GB: "United Kingdom",
+  GD: "Caribbean",
+  GE: "Georgia",
+  GL: "Greenland",
+  GR: "Greece",
+  GT: "Guatemala",
+  HK: "Hong Kong",
+  // HK: "Hong Kong S.A.R.",
+  HN: "Honduras",
+  HR: "Croatia",
+  HT: "Haiti",
+  HU: "Hungary",
+  ID: "Indonesia",
+  IE: "Ireland",
+  IL: "Israel",
+  IN: "India",
+  IQ: "Iraq",
+  IR: "Iran",
+  IS: "Iceland",
+  IT: "Italy",
+  JM: "Jamaica",
+  JO: "Jordan",
+  JP: "Japan",
+  KE: "Kenya",
+  KG: "Kyrgyzstan",
+  KH: "Cambodia",
+  KR: "South Korea",
+  KW: "Kuwait",
+  KZ: "Kazakhstan",
+  LA: "Laos",
+  LB: "Lebanon",
+  LI: "Liechtenstein",
+  LK: "Sri Lanka",
+  LT: "Lithuania",
+  LU: "Luxembourg",
+  LV: "Latvia",
+  LY: "Libya",
+  MA: "Morocco",
+  MC: "Principality of Monaco",
+  MD: "Moldava",
+  // MD: "Moldova",
+  ME: "Montenegro",
+  MK: "Former Yugoslav Republic of Macedonia",
+  ML: "Mali",
+  MM: "Myanmar",
+  MN: "Mongolia",
+  MO: "Macau S.A.R.",
+  MT: "Malta",
+  MV: "Maldives",
+  MX: "Mexico",
+  MY: "Malaysia",
+  NG: "Nigeria",
+  NI: "Nicaragua",
+  NL: "Netherlands",
+  NO: "Norway",
+  NP: "Nepal",
+  NZ: "New Zealand",
+  OM: "Oman",
+  PA: "Panama",
+  PE: "Peru",
+  PH: "Philippines",
+  PK: "Islamic Republic of Pakistan",
+  PL: "Poland",
+  PR: "Puerto Rico",
+  PT: "Portugal",
+  PY: "Paraguay",
+  QA: "Qatar",
+  RE: "Reunion",
+  RO: "Romania",
+  RS: "Serbia",
+  RU: "Russia",
+  RW: "Rwanda",
+  SA: "Saudi Arabia",
+  SE: "Sweden",
+  SG: "Singapore",
+  SI: "Slovenia",
+  SK: "Slovak",
+  SN: "Senegal",
+  SO: "Somalia",
+  SR: "Suriname",
+  SV: "El Salvador",
+  SY: "Syria",
+  TH: "Thailand",
+  TJ: "Tajikistan",
+  TM: "Turkmenistan",
+  TN: "Tunisia",
+  TR: "Turkey",
+  TT: "Trinidad and Tobago",
+  TW: "Taiwan",
+  TZ: "Tanzania",
+  UA: "Ukraine",
+  US: "United States",
+  UY: "Uruguay",
+  VA: "Vatican",
+  VE: "Venezuela",
+  VN: "Viet Nam",
+  YE: "Yemen",
+  ZA: "South Africa",
+  ZW: "Zimbabwe",
+};
diff --git a/packages/auditor-backoffice-ui/src/utils/crypto.ts 
b/packages/auditor-backoffice-ui/src/utils/crypto.ts
new file mode 100644
index 000000000..27e6ade02
--- /dev/null
+++ b/packages/auditor-backoffice-ui/src/utils/crypto.ts
@@ -0,0 +1,61 @@
+/*
+ This file is part of GNU Taler
+ (C) 2021-2023 Taler Systems S.A.
+
+ GNU Taler is free software; you can redistribute it and/or modify it under the
+ terms of the GNU General Public License as published by the Free Software
+ Foundation; either version 3, or (at your option) any later version.
+
+ GNU Taler is distributed in the hope that it will be useful, but WITHOUT ANY
+ WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
+ A PARTICULAR PURPOSE.  See the GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License along with
+ GNU Taler; see the file COPYING.  If not, see <http://www.gnu.org/licenses/>
+ */
+
+/**
+ *
+ * @author Sebastian Javier Marchano (sebasjm)
+ */
+
+const encTable = "ABCDEFGHIJKLMNOPQRSTUVWXYZ234567";
+// base32 RFC 3548
+function encodeBase32(data: ArrayBuffer) {
+  const dataBytes = new Uint8Array(data);
+  let sb = "";
+  const size = data.byteLength;
+  let bitBuf = 0;
+  let numBits = 0;
+  let pos = 0;
+  while (pos < size || numBits > 0) {
+    if (pos < size && numBits < 5) {
+      const d = dataBytes[pos++];
+      bitBuf = (bitBuf << 8) | d;
+      numBits += 8;
+    }
+    if (numBits < 5) {
+      // zero-padding
+      bitBuf = bitBuf << (5 - numBits);
+      numBits = 5;
+    }
+    const v = (bitBuf >>> (numBits - 5)) & 31;
+    sb += encTable[v];
+    numBits -= 5;
+  }
+  return sb;
+}
+
+export function isBase32RFC3548Charset(s: string): boolean {
+  for (let idx = 0; idx < s.length; idx++) {
+    const c = s.charAt(idx);
+    if (encTable.indexOf(c) === -1) return false;
+  }
+  return true;
+}
+
+export function randomBase32Key(): string {
+  var buf = new Uint8Array(20);
+  window.crypto.getRandomValues(buf);
+  return encodeBase32(buf);
+}
diff --git a/packages/auditor-backoffice-ui/src/utils/regex.test.ts 
b/packages/auditor-backoffice-ui/src/utils/regex.test.ts
new file mode 100644
index 000000000..984f1a472
--- /dev/null
+++ b/packages/auditor-backoffice-ui/src/utils/regex.test.ts
@@ -0,0 +1,88 @@
+/*
+ This file is part of GNU Taler
+ (C) 2021-2023 Taler Systems S.A.
+
+ GNU Taler is free software; you can redistribute it and/or modify it under the
+ terms of the GNU General Public License as published by the Free Software
+ Foundation; either version 3, or (at your option) any later version.
+
+ GNU Taler is distributed in the hope that it will be useful, but WITHOUT ANY
+ WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
+ A PARTICULAR PURPOSE.  See the GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License along with
+ GNU Taler; see the file COPYING.  If not, see <http://www.gnu.org/licenses/>
+ */
+
+/**
+ *
+ * @author Sebastian Javier Marchano (sebasjm)
+ */
+
+import { expect } from "chai";
+import { AMOUNT_REGEX, PAYTO_REGEX } from "./constants.js";
+
+describe("payto uri format", () => {
+  const valids = [
+    "payto://iban/DE75512108001245126199?amount=EUR:200.0&message=hello",
+    "payto://ach/122000661/1234",
+    "payto://upi/alice@example.com?receiver-name=Alice&amount=INR:200",
+    "payto://void/?amount=EUR:10.5",
+    "payto://ilp/g.acme.bob",
+  ];
+
+  it("should be valid", () => {
+    valids.forEach((v) => expect(v).match(PAYTO_REGEX));
+  });
+
+  const invalids = [
+    // has two question marks
+    "payto://iban/DE75?512108001245126199?amount=EUR:200.0&message=hello",
+    // has a space
+    "payto://ach /122000661/1234",
+    // has a space
+    "payto://upi/alice@ example.com?receiver-name=Alice&amount=INR:200",
+    // invalid field name (mount instead of amount)
+    "payto://void/?mount=EUR:10.5",
+    // payto:// is incomplete
+    "payto: //ilp/g.acme.bob",
+  ];
+
+  it("should not be valid", () => {
+    invalids.forEach((v) => expect(v).not.match(PAYTO_REGEX));
+  });
+});
+
+describe("amount format", () => {
+  const valids = [
+    "ARS:10",
+    "COL:10.2",
+    "UY:1,000.2",
+    "ARS:10.123,123",
+    "ARS:1,000,000",
+    "ARSCOL:10",
+    "LONGESTCURR:1,000,000.123,123",
+  ];
+
+
+  it("should be valid", () => {
+    valids.forEach((v) => expect(v).match(AMOUNT_REGEX));
+  });
+
+  const invalids = [
+    //no currency name
+    ":10",
+    //use . instead of ,
+    "ARS:1.000.000",
+    //currency name with numbers
+    "1ARS:10",
+    //currency name with numbers
+    "AR5:10",
+    //missing value
+    "USD:",
+  ];
+
+  it("should not be valid", () => {
+    invalids.forEach((v) => expect(v).not.match(AMOUNT_REGEX));
+  });
+});
diff --git a/packages/auditor-backoffice-ui/src/utils/table.ts 
b/packages/auditor-backoffice-ui/src/utils/table.ts
new file mode 100644
index 000000000..db2b2021c
--- /dev/null
+++ b/packages/auditor-backoffice-ui/src/utils/table.ts
@@ -0,0 +1,57 @@
+/*
+ This file is part of GNU Taler
+ (C) 2021-2023 Taler Systems S.A.
+
+ GNU Taler is free software; you can redistribute it and/or modify it under the
+ terms of the GNU General Public License as published by the Free Software
+ Foundation; either version 3, or (at your option) any later version.
+
+ GNU Taler is distributed in the hope that it will be useful, but WITHOUT ANY
+ WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
+ A PARTICULAR PURPOSE.  See the GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License along with
+ GNU Taler; see the file COPYING.  If not, see <http://www.gnu.org/licenses/>
+ */
+
+import { WithId } from "../declaration.js";
+
+/**
+ *
+ * @author Sebastian Javier Marchano (sebasjm)
+ */
+
+export interface Actions<T extends WithId> {
+  element: T;
+  type: "DELETE" | "UPDATE";
+}
+
+function notEmpty<TValue>(value: TValue | null | undefined): value is TValue {
+  return value !== null && value !== undefined;
+}
+
+export function buildActions<T extends WithId>(
+  instances: T[],
+  selected: string[],
+  action: "DELETE",
+): Actions<T>[] {
+  return selected
+    .map((id) => instances.find((i) => i.id === id))
+    .filter(notEmpty)
+    .map((id) => ({ element: id, type: action }));
+}
+
+/**
+ * For any object or array, return the same object if is not empty.
+ * not empty:
+ *  - for arrays: at least one element not undefined
+ *  - for objects: at least one property not undefined
+ * @param obj
+ * @returns
+ */
+export function undefinedIfEmpty<
+  T extends Record<string, unknown> | Array<unknown>,
+>(obj: T | undefined): T | undefined {
+  if (obj === undefined) return undefined;
+  return Object.values(obj).some((v) => v !== undefined) ? obj : undefined;
+}
diff --git a/packages/auditor-backoffice-ui/src/utils/types.ts 
b/packages/auditor-backoffice-ui/src/utils/types.ts
new file mode 100644
index 000000000..0d249f3c4
--- /dev/null
+++ b/packages/auditor-backoffice-ui/src/utils/types.ts
@@ -0,0 +1,31 @@
+/*
+ This file is part of GNU Taler
+ (C) 2021-2023 Taler Systems S.A.
+
+ GNU Taler is free software; you can redistribute it and/or modify it under the
+ terms of the GNU General Public License as published by the Free Software
+ Foundation; either version 3, or (at your option) any later version.
+
+ GNU Taler is distributed in the hope that it will be useful, but WITHOUT ANY
+ WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
+ A PARTICULAR PURPOSE.  See the GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License along with
+ GNU Taler; see the file COPYING.  If not, see <http://www.gnu.org/licenses/>
+ */
+
+import { VNode } from "preact";
+
+export interface KeyValue {
+  [key: string]: string;
+}
+
+export interface Notification {
+  message: string;
+  description?: string | VNode;
+  details?: string | VNode;
+  type: MessageType;
+}
+
+export type ValueOrFunction<T> = T | ((p: T) => T);
+export type MessageType = "INFO" | "WARN" | "ERROR" | "SUCCESS";
diff --git a/packages/auditor-backoffice-ui/test.mjs 
b/packages/auditor-backoffice-ui/test.mjs
new file mode 100755
index 000000000..be76348e5
--- /dev/null
+++ b/packages/auditor-backoffice-ui/test.mjs
@@ -0,0 +1,31 @@
+#!/usr/bin/env node
+/*
+ This file is part of GNU Taler
+ (C) 2021-2023 Taler Systems S.A.
+
+ GNU Taler is free software; you can redistribute it and/or modify it under the
+ terms of the GNU General Public License as published by the Free Software
+ Foundation; either version 3, or (at your option) any later version.
+
+ GNU Taler is distributed in the hope that it will be useful, but WITHOUT ANY
+ WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
+ A PARTICULAR PURPOSE.  See the GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License along with
+ GNU Taler; see the file COPYING.  If not, see <http://www.gnu.org/licenses/>
+ */
+
+import { build } from "@gnu-taler/web-util/build";
+import { getFilesInDirectory } from "@gnu-taler/web-util/build";
+
+const allTestFiles = getFilesInDirectory("src", /.test.tsx?$/);
+
+await build({
+  type: "test",
+  source: {
+    js: allTestFiles.files,
+    assets: [{base:"src",files:["src/index.html"]}],
+  },
+  destination: "./dist/test",
+  css: "sass",
+});
diff --git a/packages/auditor-backoffice-ui/tsconfig.json 
b/packages/auditor-backoffice-ui/tsconfig.json
new file mode 100644
index 000000000..396f1e9e7
--- /dev/null
+++ b/packages/auditor-backoffice-ui/tsconfig.json
@@ -0,0 +1,58 @@
+{
+  "compilerOptions": {
+    /* Basic Options */
+    "target": "ES2020" /* Specify ECMAScript target version: 'ES3' (default), 
'ES5', 'ES2015', 'ES2016', 'ES2017', or 'ESNEXT'. */,
+    "module": "Node16" /* Specify module code generation: 'none', commonjs', 
'amd', 'system', 'umd', 'es2015', or 'ESNext'. */,
+    "lib": [
+      "es2020",
+      "dom"
+    ] /* Specify library files to be included in the compilation:  */,
+    // "allowJs": true,                          /* Allow javascript files to 
be compiled. */
+    // "checkJs": true,                       /* Report errors in .js files. */
+    "jsx": "react" /* Specify JSX code generation: 'preserve', 'react-native', 
or 'react'. */,
+    "jsxFactory": "h" /* Specify the JSX factory function to use when 
targeting react JSX emit, e.g. React.createElement or h. */,
+    "jsxFragmentFactory": "Fragment", // 
https://www.typescriptlang.org/docs/handbook/release-notes/typescript-4-0.html#custom-jsx-factories
+    // "declaration": true,                   /* Generates corresponding 
'.d.ts' file. */
+    // "sourceMap": true,                     /* Generates corresponding 
'.map' file. */
+    // "outFile": "./",                       /* Concatenate and emit output 
to single file. */
+    // "outDir": "./",                        /* Redirect output structure to 
the directory. */
+    // "rootDir": "./",                       /* Specify the root directory of 
input files. Use to control the output directory structure with --outDir. */
+    // "removeComments": true,                /* Do not emit comments to 
output. */
+    "noEmit": true /* Do not emit outputs. */,
+    // "importHelpers": true,                 /* Import emit helpers from 
'tslib'. */
+    // "downlevelIteration": true,            /* Provide full support for 
iterables in 'for-of', spread, and destructuring when targeting 'ES5' or 'ES3'. 
*/
+    // "isolatedModules": true,               /* Transpile each file as a 
separate module (similar to 'ts.transpileModule'). */
+    /* Strict Type-Checking Options */
+    "strict": true /* Enable all strict type-checking options. */,
+    // "noImplicitAny": true,                 /* Raise error on expressions 
and declarations with an implied 'any' type. */
+    // "strictNullChecks": true,              /* Enable strict null checks. */
+    // "noImplicitThis": true,                /* Raise error on 'this' 
expressions with an implied 'any' type. */
+    // "alwaysStrict": true,                  /* Parse in strict mode and emit 
"use strict" for each source file. */
+    /* Additional Checks */
+    // "noUnusedLocals": true,                /* Report errors on unused 
locals. */
+    // "noUnusedParameters": true,            /* Report errors on unused 
parameters. */
+    // "noImplicitReturns": true,             /* Report error when not all 
code paths in function return a value. */
+    // "noFallthroughCasesInSwitch": true,    /* Report errors for fallthrough 
cases in switch statement. */
+    /* Module Resolution Options */
+    "moduleResolution": "node16" /* Specify module resolution strategy: 'node' 
(Node.js) or 'classic' (TypeScript pre-1.6). */,
+    "esModuleInterop": true /* */,
+    // "baseUrl": "./",                       /* Base directory to resolve 
non-absolute module names. */
+    // "paths": {},                           /* A series of entries which 
re-map imports to lookup locations relative to the 'baseUrl'. */
+    // "rootDirs": [],                        /* List of root folders whose 
combined content represents the structure of the project at runtime. */
+    // "typeRoots": [],                       /* List of folders to include 
type definitions from. */
+    // "types": [],                           /* Type declaration files to be 
included in compilation. */
+    // "allowSyntheticDefaultImports": true,  /* Allow default imports from 
modules with no default export. This does not affect code emit, just 
typechecking. */
+    // "preserveSymlinks": true,              /* Do not resolve the real path 
of symlinks. */
+    /* Source Map Options */
+    // "sourceRoot": "./",                    /* Specify the location where 
debugger should locate TypeScript files instead of source locations. */
+    // "mapRoot": "./",                       /* Specify the location where 
debugger should locate map files instead of generated locations. */
+    // "inlineSourceMap": true,               /* Emit a single file with 
source maps instead of having a separate file. */
+    // "inlineSources": true,                 /* Emit the source alongside the 
sourcemaps within a single file; requires '--inlineSourceMap' or '--sourceMap' 
to be set. */
+    /* Experimental Options */
+    // "experimentalDecorators": true,        /* Enables experimental support 
for ES7 decorators. */
+    // "emitDecoratorMetadata": true,         /* Enables experimental support 
for emitting type metadata for decorators. */
+    /* Advanced Options */
+    "skipLibCheck": true /* Skip type checking of declaration files. */
+  },
+  "include": ["src/**/*", "tests/**/*"]
+}

-- 
To stop receiving notification emails like this one, please contact
gnunet@gnunet.org.



reply via email to

[Prev in Thread] Current Thread [Next in Thread]