# Introduction URL: /introduction Welcome to the Montonio developer documentation. Here you will find all the information you need to integrate with our services. There are two main ways for integrating Montonio: using ready-made plugins or by doing a custom integration with our API. Choose the approach you feel most comfortable with. :::tip Use your AI agent to help integrate Montonio into your shop. Point it to /llms.txt and ask for help. ::: ## 1. Plugins If you use a popular e-commerce platform such as WooCommerce, Magento, PrestaShop, and some others, we recommend using our ready-made plugins. They are easy to install and will allow you to start using Montonio's services in a matter of minutes. Visit the integrations page on our website and choose your platform to get started. ## 2. Build your own integration If you are using a custom e-commerce platform or want to build your own integration, you can use our API. Head over to the relevant section of the documentation to get started: ## API keys Whether you choose to use plugins or build your own integration, you will need to use API keys to access Montonio's services. The keys can be acquired for 2 environments: **Sandbox** and **Production**. Both sets of keys can be acquired from the Montonio Partner System. To get an account and access the Partner System, please fill in the registration form on our website. Once you have an account set up in the Partner System you can access API keys for the sandbox environment and use them to test Montonio's services. Production keys will become available once you complete your profile and your business is approved by Montonio. :::caution You can generate the keys under the `Stores` page of the Partner System. Click on your store and navigate to the `API Keys` tab. ::: Note: When generating new keys, old ones will become invalid automatically. If you have any questions regarding the docs, please contact our support team at [support@montonio.com](mailto:support@montonio.com). --- # Hire-Purchase URL: /api/hire-purchase :::caution This documentation describes our old Hire Purchase solution which is deprecated as of January 31, 2024. Please refer to our [Financing](/api/stargate/guides/financing) documentation for the latest version. ::: To start a Hire-Purchase application, a JWT (JSON Web Token) with payment instructions must be generated using your Secret Key. The customer will then be redirected to the Montonio Hire-Purchase client (financing.montonio.com) with this token as a query parameter. ## Generating the Payment Token The parameters of the token's header and payload are described below. The JWT is signed with your Secret Key using HMAC SHA256 (HS256). The exact implementation of how to generate the JWT varies by programming language and you can see some examples on the code panel. Don't forget to choose your preferred language! 🙂 :::note We recommend using popular community maintained libraries for JWT generation. You can browse the libraries for your programming language on the [jwt.io](https://jwt.io) website. ::: Show / Hide Parameters Headers | Key | Required | Type | Description | | --- | -------- | -------- | ---------------------- | | alg | yes | `string` | Must be set to `HS256` | | typ | yes | `string` | Must be set to `JWT` | Payload | Key | Required | Type | Description | | ------------------------------------- | ----------- | --------- | ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | | loan\_type | yes | `string` | `"hire_purchase"` | | access\_key | yes | `string` | Your Access Key for desired environment | | currency | yes | `string` | ISO 4217 alphabetic currency code (currently only `EUR` is supported) | | merchant\_reference | yes | `string` | The order reference in the merchant system | | checkout\_products | yes | `array` | Array of products, see below | | checkout\_first\_name | yes\* | `string` | The customer's first name. Use this to identify customers more easily in Montonio's Partner System. | | checkout\_last\_name | yes\* | `string` | The customer's last name. Use this to identify customers more easily in Montonio's Partner System. | | checkout\_email | recommended | `string` | The customer's e-mail address. Use this to identify customers more easily in Montonio's Partner System. | | checkout\_phone\_number | recommended | `string` | The customer's phone number. Use this to identify customers more easily in Montonio's Partner System. | | checkout\_city | recommended | `string` | The city of the customer address | | checkout\_address | recommended | `string` | The address of the customer | | checkout\_postal\_code | recommended | `string` | The postal code (zip) of the customer | | preselected\_country | no | `string` | The preferred country for the application. Defaults to the merchant's country, if available. Available values are `EE` (others in development). | | preselected\_locale | recommended | `string` | available: `et` , `en_US` , `lt` | | preselected\_loan\_period | recommended | `integer` | The customer's preselected loan period chosen in the e-store. (values `3`-`60`) | | merchant\_return\_url | recommended | `string` | The URL where the customer will be redirected back to after completing or cancelling a payment. [See below for details](#validating-the-financing-application) on financing application verification. | | merchant\_notification\_url | recommended | `string` | The URL to send a webhook notification to once a loan agreement has been signed. [See below for details](#webhook-notification) | | \*Required for Lithuanian stores only | | | | Payload: Products | Key | Required | Type | Description | | -------------- | -------- | ------------ | --------------------------------------- | | product\_name | yes | `string` | The product's name | | product\_price | yes | `float %.2f` | The product's sale price (tax included) | | quantity | yes | `integer` | Quantity of this product | :::caution Please make sure that the `product_price` is the price of the product for a quantity of 1. Montonio's API will multiply the individual product's price by the product's quantity on the server-side. ::: :::note The token's expiration time should be long enough to ensure that the customer arrives to Montonio's gateway in time but no longer than 10 minutes from the issuing time. Note that the expiration time will be validated only upon arrival to the gateway and that the customer can take longer than 10 minutes to complete the process. ::: Show / Hide Code Examples ```javascript /** * We recommend using the jsonwebtoken package to generate * Json Web Tokens. You can install it with npm: * > npm install jsonwebtoken * More information can be found at * https://www.npmjs.com/package/jsonwebtoken */ const jwt = require('jsonwebtoken'); const payload = { "loan_type": "hire_purchase", "access_key": "your_access_key", "currency": "EUR", "merchant_reference":"O036869", "checkout_first_name":"John", "checkout_last_name":"Smith", "checkout_email":"info@montonio.com", "checkout_phone":"5555555", "checkout_city":"Tallinn", "checkout_address":"Telliskivi 60a", "checkout_postal_code":"10412", "merchant_return_url": "https://mystore.com/montonio/payment/return?orderId=O036869" "merchant_notification_url": "https://mystore.com/montonio/payment/webhook?orderId=O036869", "preselected_locale": "et", "preselected_loan_period": 12, "checkout_products":[ { "product_name":"Shiny New Computer T490s", "product_price":1578.85, "quantity":2 }, { "product_name":"Standard delivery charges", "product_price":5, "quantity":1 } ], } const token = jwt.sign( payload, 'merchant_secret_key', { algorithm: 'HS256', expiresIn: '10m' } ); console.log(token); ``` ```php 'hire_purchase', 'access_key' => $accessKey, 'currency' => 'EUR', 'merchant_reference' => 'my-order-id-1', 'checkout_first_name' => 'Montonio', 'checkout_last_name' => 'Test', 'checkout_email' => 'test@montonio.com', 'checkout_phone_number' => '+37255555555', 'checkout_city' => 'Tallinn', 'checkout_address' => 'Customer Address', 'checkout_postal_code' => '11111', 'merchant_return_url' => 'https://my-store/return', // Where to redirect the checkout to after the payment 'merchant_notification_url' => 'https://my-store/notify', // We will send a webhook after the payment is complete, 'preselected_locale' => 'et' 'preselected_loan_period' => 12 'checkout_products' => array(), ); // Add products $paymentData['checkout_products'][] = array( 'quantity' => (int) 1, 'product_name' => 'Some product name', 'product_price' => 35.52, ); /********************************************* * MONTONIO FINANCING * ******************************************/ $montonioFinancing = new MontonioFinancingSDK( $accessKey, $secretKey, $env ); $montonioFinancing->setPaymentData($paymentData); $financingPaymentUrl = $montonioFinancing->getPaymentUrl(); echo $financingPaymentUrl; ``` ```php composer require firebase/php-jwt * More information can be found at * https://github.com/firebase/php-jwt */ // Should be loaded only once in the app, check composer docs for the specific framework you are using require __DIR__ . '/vendor/autoload.php'; use \Firebase\JWT\JWT; $payment_data = [ 'access_key' => 'MERCHANT_ACCESS_KEY', // ... 'iat' => time(), 'exp' => time() + (60 * 10) ]; $token = JWT::encode($payload, 'MERCHANT_SECRET_KEY', 'HS256'); // var_dump($token); // eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJhY2Nlc3Nfa2V5IjoibWVyY2hhbnRfYWNjZXNzX2tleSIsImlhdCI6MTYwMzcxMTQ3NSwiZXhwIjoxNjAzNzE1MDc1fQ.UYwRQXykcIVNzIjni3icf_FBbxSXZ_m-2SsFfz3zjBs ``` ```python ''' We recommend using the PyJWT package to generate Json Web Tokens. You can install it with pip: > pip3 install PyJWT datetime More information can be found at https://pyjwt.readthedocs.io/en/latest/ ''' import jwt from datetime import datetime, timedelta, timezone payment_data = { 'access_key': 'merchant_access_key', # ... 'iat': datetime.now(timezone.utc), 'exp': datetime.now(timezone.utc) + timedelta(minutes=10) } payment_token = jwt.encode( payment_data, 'merchant_secret_key', algorithm='HS256' ).decode('utf-8') print(payment_token) # eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJhY2Nlc3Nfa2V5IjoibWVyY2hhbnRfYWNjZXNzX2tleSIsImlhdCI6MTYwMzcxMTQ3NSwiZXhwIjoxNjAzNzE1MDc1fQ.UYwRQXykcIVNzIjni3icf_FBbxSXZ_m-2SsFfz3zjBs ``` ## Redirecting the Customer Once you have generated the payment token it's time to redirect the customer to Montonio's gateway. Append the `payment_token` to the gateway URL as a query parameter. Sandbox: [https://sandbox-financing.montonio.com](https://sandbox-financing.montonio.com) Production: [https://financing.montonio.com](https://financing.montonio.com) Example: ```console https://sandbox-financing.montonio.com?payment_token=eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJhbW91bnQiOjEwLCJjdXJyZW5jeSI6IkVVUiIsImFjY2Vzc19rZXkiOiJtZXJjaGFudF9hY2Nlc3Nfa2V5IiwibWVyY2hhbnRfcmVmZXJlbmNlIjoiU082NjExMjMiLCJtZXJjaGFudF9yZXR1cm5fdXJsIjoiaHR0cHM6Ly9tb250b25pby5jb20vb3JkZXJzLzI3NzMxNzczL3RoYW5rX3lvdSIsIm1lcmNoYW50X25vdGlmaWNhdGlvbl91cmwiOiJodHRwczovL21vbnRvbmlvLmNvbS9vcmRlcnMvcGF5bWVudF93ZWJob29rIiwicGF5bWVudF9pbmZvcm1hdGlvbl91bnN0cnVjdHVyZWQiOiJQYXltZW50IGZvciBvcmRlciBTTzY2MTEyMyIsInByZXNlbGVjdGVkX2FzcHNwIjoiTEhWQkVFMjIiLCJwcmVzZWxlY3RlZF9sb2NhbGUiOiJldCIsImNoZWNrb3V0X2VtYWlsIjoidGVzdC1jdXN0b21lckBtb250b25pby5jb20iLCJpYXQiOjE2MDEwMjA4MjUsImV4cCI6MTYwMTAyMTQyNX0.RfRVHklL7irHGN309AYRTMOXnq6UWYT2Mxb42oMh4JY ``` Example: ```console https://financing.montonio.com?payment_token=eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJhbW91bnQiOjEwLCJjdXJyZW5jeSI6IkVVUiIsImFjY2Vzc19rZXkiOiJtZXJjaGFudF9hY2Nlc3Nfa2V5IiwibWVyY2hhbnRfcmVmZXJlbmNlIjoiU082NjExMjMiLCJtZXJjaGFudF9yZXR1cm5fdXJsIjoiaHR0cHM6Ly9tb250b25pby5jb20vb3JkZXJzLzI3NzMxNzczL3RoYW5rX3lvdSIsIm1lcmNoYW50X25vdGlmaWNhdGlvbl91cmwiOiJodHRwczovL21vbnRvbmlvLmNvbS9vcmRlcnMvcGF5bWVudF93ZWJob29rIiwicGF5bWVudF9pbmZvcm1hdGlvbl91bnN0cnVjdHVyZWQiOiJQYXltZW50IGZvciBvcmRlciBTTzY2MTEyMyIsInByZXNlbGVjdGVkX2FzcHNwIjoiTEhWQkVFMjIiLCJwcmVzZWxlY3RlZF9sb2NhbGUiOiJldCIsImNoZWNrb3V0X2VtYWlsIjoidGVzdC1jdXN0b21lckBtb250b25pby5jb20iLCJpYXQiOjE2MDEwMjA4MjUsImV4cCI6MTYwMTAyMTQyNX0.RfRVHklL7irHGN309AYRTMOXnq6UWYT2Mxb42oMh4JY ``` ## Validating the Financing Application ### Redirect Back to the Merchant Once the customer completes the financing application, they will be redirected back to the `merchant_return_url` that you set in the original payment token with a new `payment_token` appended to the URL as a query parameter. Validate the contents and the signature of this token to confirm the order. [See below for details](#validating-the-returned-payment-token) on validating the token. Example return URL: ```console https://my-store.com/orders/27731773/thank_you?payment_token=eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJhbW91bnQiOjU3OC44NSwiY3VycmVuY3kiOiJFVVIiLCJhY2Nlc3Nfa2V5IjoiYzYxOWI1ZmQtOWYwNS00ZGY1LTlhNDEtYTIwODAzZDMzZGYwIiwibWVyY2hhbnRfcmVmZXJlbmNlIjoiU08wMzYtNDIyMiIsInN0YXR1cyI6ImZpbmFsaXplZCIsImFwcGxpY2F0aW9uX3V1aWQiOiJhZTRjYjIzZS1hZWRjLTQ4YzUtYmU0MC1iM2EwYTEzZjMzZmMiLCJwYXltZW50X21ldGhvZF9uYW1lIjoiU2xpY2UiLCJpYXQiOjE2MjI3Mjk0MjYsImV4cCI6MTYyMjc0MzgyNn0.ruT9q6dSQcV4y5dwPwov6Tr0s5FDuIks1Ayd8lxdBe4 ``` ### Webhook Notification Once you set the `merchant_notification_url` parameter in the original payment token, we will send a `POST` request to this URL with a new `payment_token` appended to it as a query parameter. Validate the contents and the signature of this token to confirm the order. [See below for details](#validating-the-returned-payment-token) on validating the token. ### Validating the Returned Payment Token The `payment_token` that is appended to the `merchant_return_url` when redirecting back to the merchant or to the `merchant_notification_url` when sending a webhook notification needs to be validated. The token is signed with your `Secret Key`. On the code panel you can see examples of validating the token. Show / Hide Parameters Headers | Key | Type | Description | | --- | -------- | --------------------- | | alg | `string` | Always set to `HS256` | | typ | `string` | Always set to `JWT` | Payload | Key | Type | Description | | --------------------- | -------- | ---------------------------------------------------------------------------------------- | | amount | `number` | Payment amount (up to 2 decimal places). | | currency | `string` | Currency used to placed the order (ISO 4217). | | access\_key | `string` | Your `Access Key` obtained from the Partner System. | | merchant\_reference | `string` | The order reference number you provided in the initial payment token. | | status | `string` | Payment status. Only consider `finalized` as the correct status for a completed payment. | | application\_uuid | `string` | The loan application ID in Montonio's system. | | payment\_method\_name | `string` | The friendly name of the payment method. | | exp | `number` | Expiration time of the token in Unix time. | | iat | `number` | Issuing time of the token in Unix time. | Show / Hide Code Examples ```javascript /** * We recommend using the jsonwebtoken package to verify * Json Web Tokens. You can install it with npm: * > npm install jsonwebtoken * More information can be found at * https://www.npmjs.com/package/jsonwebtoken */ const jwt = require('jsonwebtoken'); // fetched from the URL const payment_token = 'eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJhbW91bnQiOjU3OC44NSwiY3VycmVuY3kiOiJFVVIiLCJhY2Nlc3Nfa2V5IjoiYzYxOWI1ZmQtOWYwNS00ZGY1LTlhNDEtYTIwODAzZDMzZGYwIiwibWVyY2hhbnRfcmVmZXJlbmNlIjoiU08wMzYtNDIyMiIsInN0YXR1cyI6ImZpbmFsaXplZCIsImFwcGxpY2F0aW9uX3V1aWQiOiJhZTRjYjIzZS1hZWRjLTQ4YzUtYmU0MC1iM2EwYTEzZjMzZmMiLCJwYXltZW50X21ldGhvZF9uYW1lIjoiU2xpY2UiLCJpYXQiOjE2MjI3Mjk0MjYsImV4cCI6MTYyMjc0MzgyNn0.ruT9q6dSQcV4y5dwPwov6Tr0s5FDuIks1Ayd8lxdBe4'; // original order ID passed to merchant_reference const orderID = 'SO661123'; const decoded = jwt.verify(payment_token, 'merchant_secret_key'); if ( decoded.access_key === 'merchant_access_key' && decoded.merchant_reference === orderID && decoded.status === 'finalized' ) { // payment completed } else { // payment not completed } ``` ```php composer require firebase/php-jwt * More information can be found at * https://github.com/firebase/php-jwt */ use \Firebase\JWT\JWT; // fetched from the URL $payment_token = 'eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJhbW91bnQiOjU3OC44NSwiY3VycmVuY3kiOiJFVVIiLCJhY2Nlc3Nfa2V5IjoiYzYxOWI1ZmQtOWYwNS00ZGY1LTlhNDEtYTIwODAzZDMzZGYwIiwibWVyY2hhbnRfcmVmZXJlbmNlIjoiU08wMzYtNDIyMiIsInN0YXR1cyI6ImZpbmFsaXplZCIsImFwcGxpY2F0aW9uX3V1aWQiOiJhZTRjYjIzZS1hZWRjLTQ4YzUtYmU0MC1iM2EwYTEzZjMzZmMiLCJwYXltZW50X21ldGhvZF9uYW1lIjoiU2xpY2UiLCJpYXQiOjE2MjI3Mjk0MjYsImV4cCI6MTYyMjc0MzgyNn0.ruT9q6dSQcV4y5dwPwov6Tr0s5FDuIks1Ayd8lxdBe4'; // original order ID passed to merchant_reference $orderID = 'SO661123'; $decoded = Firebase\JWT\JWT::decode( $payment_token, 'merchant_secret_key', array('HS256') ); if ( $decoded->access_key === 'merchant_access_key' && $decoded->merchant_reference === $orderID && $decoded->status === 'finalized' ) { // payment completed } else { // payment not completed } ?> ``` ```python ''' We recommend using the PyJWT package to verify Json Web Tokens. You can install it with pip: > pip3 install PyJWT More information can be found at https://pyjwt.readthedocs.io/en/latest/ ''' import jwt # fetched from the URL payment_token = 'eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJhbW91bnQiOjU3OC44NSwiY3VycmVuY3kiOiJFVVIiLCJhY2Nlc3Nfa2V5IjoiYzYxOWI1ZmQtOWYwNS00ZGY1LTlhNDEtYTIwODAzZDMzZGYwIiwibWVyY2hhbnRfcmVmZXJlbmNlIjoiU08wMzYtNDIyMiIsInN0YXR1cyI6ImZpbmFsaXplZCIsImFwcGxpY2F0aW9uX3V1aWQiOiJhZTRjYjIzZS1hZWRjLTQ4YzUtYmU0MC1iM2EwYTEzZjMzZmMiLCJwYXltZW50X21ldGhvZF9uYW1lIjoiU2xpY2UiLCJpYXQiOjE2MjI3Mjk0MjYsImV4cCI6MTYyMjc0MzgyNn0.ruT9q6dSQcV4y5dwPwov6Tr0s5FDuIks1Ayd8lxdBe4' # original order ID passed to merchant_reference orderID = 'SO661123'; try: decoded = jwt.decode( payment_token, 'merchant_secret_key', algorithms=['HS256'] ) except jwt.exceptions.InvalidSignatureError as identifier: pass # Token validation failed if ( decoded['access_key'] == 'merchant_access_key' and decoded['merchant_reference'] == orderID and decoded['status'] == 'finalized' ): pass # payment completed else: pass # payment not completed ``` [Head back to Montonio](https://www.montonio.com) --- # Payments V1 URL: /api/payments :::caution This article contains deprecated information and should not be used for new integrations. If you want to integrate payments with Montonio, please use the [up to date integration information.](/api/stargate/overview) ::: Welcome to the Montonio Payments API Developer Documentation. Here you can find instructions for how to integrate with **Montonio Payments**. \*Please note that Card Payments are not available in the Sandbox environment, but may be tested with Stripe test cards in Production. ## Initiating a Payment To start the payment initiation flow, a JWT (JSON Web Token) with payment instructions must be generated using your `Secret Key`. The customer shall then be redirected to our payment gateway with this token as a query parameter. ### Generating the Payment Token The parameters of the token's header and payload are described below. The JWT is signed with your `Secret Key` using HMAC SHA256 (HS256). The exact implementation of how to generate the JWT varies by programming language and you can see some examples on the code panel. Don't forget to choose your preferred language! 🙂 :::note We recommend using popular community maintained libraries for JWT generation. You can browse the libraries for your programming language on the [jwt.io](https://jwt.io) website. ::: Show / Hide Parameters Headers | Key | Required | Type | Description | | --- | -------- | -------- | ---------------------- | | alg | yes | `string` | Must be set to `HS256` | | typ | yes | `string` | Must be set to `JWT` | Payload | Key | Required | Type | Description | | ---------------------------------- | -------- | -------- | ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | | amount | yes | `number` | Payment amount (up to 2 decimal places). | | currency | yes | `string` | Payment currency. Currently `EUR` and `PLN` are supported. | | access\_key | yes | `string` | Your `Access Key` obtained from the Partner System. | | merchant\_reference | yes | `string` | The order reference in the merchant's system (e.g. the order ID). | | exp | yes | `number` | Expiration time of the token in Unix time. Set that to 10 minutes from the time of issuing the token. | | merchant\_return\_url | yes | `string` | The URL where the customer will be redirected back to after completing or cancelling a payment. [See below for details](#validating-the-payment) on payment verification. | | merchant\_notification\_url | yes | `string` | The URL to send a webhook notification when a payment is completed. [See below for details](#validating-the-payment) on payment verification. | | payment\_information\_unstructured | no | `string` | Description of the payment that will be relayed to the bank's payment order. If left blank, it will default to the value of `merchant_reference`. | | payment\_information\_structured | no | `string` | Structured payment reference number. This is a standardised reference number used for accounting purposes and will be validated by banks. Leave blank if you do not use reference numbers to link payments. | | preselected\_aspsp | no | `string` | The bank that the customer chose for this payment if you allow them to select their bank of choice in your checkout. Leave this blank to let the customer choose their bank in our interface. [See below for details](#displaying-the-list-of-available-banks) on how to fetch the list of available banks. | | preselected\_country | no | `string` | The preferred country for the methods list of the payment gateway. Defaults to the merchant's country. Available values are `EE`, `LV`, `LT`, `FI`, `PL`. | | preselected\_locale | no | `string` | The preferred language of the payment gateway. Defaults to the merchant country's official language. Available values are `en_US`, `et`, `lt`, `ru`, `pl`, `fi`, `lv`. | | checkout\_email | no | `string` | The customer's e-mail address. Use this to identify customers more easily in Montonio's Partner System. | | checkout\_phone\_number | no | `string` | The customer's phone number. Use this to identify customers more easily in Montonio's Partner System. | | checkout\_first\_name | no | `string` | The customer's first name. Use this to identify customers more easily in Montonio's Partner System. | | checkout\_last\_name | no | `string` | The customer's last name. Use this to identify customers more easily in Montonio's Partner System. | :::note The token's expiration time should be long enough to ensure that the customer arrives to Montonio's gateway in time but no longer than 10 minutes from the issuing time. Note that the expiration time will be validated only upon arrival to the gateway and that the customer can take longer than 10 minutes to complete the process. ::: Show / Hide Code Examples ```javascript /** * We recommend using the jsonwebtoken package to generate * Json Web Tokens. You can install it with npm: * > npm install jsonwebtoken * More information can be found at * https://www.npmjs.com/package/jsonwebtoken */ const jwt = require('jsonwebtoken'); const payload = { amount: 10, currency: 'EUR', access_key: 'merchant_access_key', merchant_reference: 'SO661123', merchant_return_url: 'https://montonio.com/orders/27731773/thank_you', merchant_notification_url: 'https://montonio.com/orders/payment_webhook', payment_information_unstructured: 'Payment for order SO661123', preselected_aspsp: 'LHVBEE22', preselected_locale: 'et', checkout_email: 'test-customer@montonio.com' } const token = jwt.sign( payload, 'merchant_secret_key', { algorithm: 'HS256', expiresIn: '10m' } ); console.log(token); // eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJhbW91bnQiOjEwLCJjdXJyZW5jeSI6IkVVUiIsImFjY2Vzc19rZXkiOiJtZXJjaGFudF9hY2Nlc3Nfa2V5IiwibWVyY2hhbnRfcmVmZXJlbmNlIjoiU082NjExMjMiLCJtZXJjaGFudF9yZXR1cm5fdXJsIjoiaHR0cHM6Ly9tb250b25pby5jb20vb3JkZXJzLzI3NzMxNzczL3RoYW5rX3lvdSIsIm1lcmNoYW50X25vdGlmaWNhdGlvbl91cmwiOiJodHRwczovL21vbnRvbmlvLmNvbS9vcmRlcnMvcGF5bWVudF93ZWJob29rIiwicGF5bWVudF9pbmZvcm1hdGlvbl91bnN0cnVjdHVyZWQiOiJQYXltZW50IGZvciBvcmRlciBTTzY2MTEyMyIsInByZXNlbGVjdGVkX2FzcHNwIjoiTEhWQkVFMjIiLCJwcmVzZWxlY3RlZF9sb2NhbGUiOiJldCIsImNoZWNrb3V0X2VtYWlsIjoidGVzdC1jdXN0b21lckBtb250b25pby5jb20iLCJpYXQiOjE2MDEwMjA4MjUsImV4cCI6MTYwMTAyMTQyNX0.RfRVHklL7irHGN309AYRTMOXnq6UWYT2Mxb42oMh4JY ``` ```php composer require firebase/php-jwt * More information can be found at * https://github.com/firebase/php-jwt */ use \Firebase\JWT\JWT; $payment_data = array( 'amount' => 10, 'currency' => 'EUR', 'access_key' => 'merchant_access_key', 'merchant_reference' => 'SO661123', 'merchant_return_url' => 'https://montonio.com/orders/27731773/thank_you', 'merchant_notification_url' => 'https://montonio.com/orders/payment_webhook', 'payment_information_unstructured' => 'Payment for order SO661123', 'preselected_aspsp' => 'LHVBEE22', 'preselected_locale' => 'et', 'checkout_email' => 'test-customer@montonio.com', 'exp' => time() + (60 * 10), ); $payment_token = \Firebase\JWT\JWT::encode($payment_data, 'merchant_secret_key', 'HS256'); echo $payment_token; // eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJhbW91bnQiOjEwLCJjdXJyZW5jeSI6IkVVUiIsImFjY2Vzc19rZXkiOiJtZXJjaGFudF9hY2Nlc3Nfa2V5IiwibWVyY2hhbnRfcmVmZXJlbmNlIjoiU082NjExMjMiLCJtZXJjaGFudF9yZXR1cm5fdXJsIjoiaHR0cHM6Ly9tb250b25pby5jb20vb3JkZXJzLzI3NzMxNzczL3RoYW5rX3lvdSIsIm1lcmNoYW50X25vdGlmaWNhdGlvbl91cmwiOiJodHRwczovL21vbnRvbmlvLmNvbS9vcmRlcnMvcGF5bWVudF93ZWJob29rIiwicGF5bWVudF9pbmZvcm1hdGlvbl91bnN0cnVjdHVyZWQiOiJQYXltZW50IGZvciBvcmRlciBTTzY2MTEyMyIsInByZXNlbGVjdGVkX2FzcHNwIjoiTEhWQkVFMjIiLCJwcmVzZWxlY3RlZF9sb2NhbGUiOiJldCIsImNoZWNrb3V0X2VtYWlsIjoidGVzdC1jdXN0b21lckBtb250b25pby5jb20iLCJpYXQiOjE2MDEwMjA4MjUsImV4cCI6MTYwMTAyMTQyNX0.RfRVHklL7irHGN309AYRTMOXnq6UWYT2Mxb42oMh4JY ?> ``` ```python ''' We recommend using the PyJWT package to generate Json Web Tokens. You can install it with pip: > pip3 install PyJWT More information can be found at https://pyjwt.readthedocs.io/en/latest/ ''' import jwt from datetime import datetime, timedelta, datetime payment_data = { 'amount': 10, 'currency': 'EUR', 'access_key': 'merchant_access_key', 'merchant_reference': 'SO661123', 'merchant_return_url': 'https://montonio.com/orders/27731773/thank_you', 'merchant_notification_url': 'https://montonio.com/orders/payment_webhook', 'payment_information_unstructured': 'Payment for order SO661123', 'preselected_aspsp': 'LHVBEE22', 'preselected_locale': 'et', 'checkout_email': 'test-customer@montonio.com', 'exp': datetime.now(timezone.utc) + timedelta(minutes=10) } payment_token = jwt.encode( payment_data, 'merchant_secret_key', algorithm='HS256' ).decode('utf-8') print(payment_token) # eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJhbW91bnQiOjEwLCJjdXJyZW5jeSI6IkVVUiIsImFjY2Vzc19rZXkiOiJtZXJjaGFudF9hY2Nlc3Nfa2V5IiwibWVyY2hhbnRfcmVmZXJlbmNlIjoiU082NjExMjMiLCJtZXJjaGFudF9yZXR1cm5fdXJsIjoiaHR0cHM6Ly9tb250b25pby5jb20vb3JkZXJzLzI3NzMxNzczL3RoYW5rX3lvdSIsIm1lcmNoYW50X25vdGlmaWNhdGlvbl91cmwiOiJodHRwczovL21vbnRvbmlvLmNvbS9vcmRlcnMvcGF5bWVudF93ZWJob29rIiwicGF5bWVudF9pbmZvcm1hdGlvbl91bnN0cnVjdHVyZWQiOiJQYXltZW50IGZvciBvcmRlciBTTzY2MTEyMyIsInByZXNlbGVjdGVkX2FzcHNwIjoiTEhWQkVFMjIiLCJwcmVzZWxlY3RlZF9sb2NhbGUiOiJldCIsImNoZWNrb3V0X2VtYWlsIjoidGVzdC1jdXN0b21lckBtb250b25pby5jb20iLCJpYXQiOjE2MDEwMjA4MjUsImV4cCI6MTYwMTAyMTQyNX0.RfRVHklL7irHGN309AYRTMOXnq6UWYT2Mxb42oMh4JY ``` ### Card Payments With Stripe Montonio processes card payments through Stripe. After you have completed the Stripe onboarding through Montonio's Partner System, you can set the value of `preselected_aspsp` to `CARD` in order to direct your customer through the card payment flow. \*Please note that Card Payments are not available in the Sandbox environment, but may be tested with Stripe test cards in Production. If you don't set the preselected\_aspsp parameter, the customer can choose to pay by card in our interface. The Visa/Mastercard button is displayed next to the banks' logos. ### Redirecting the Customer Once you have generated the payment token it's time to redirect the customer to Montonio's gateway. Append the `payment_token` to the gateway URL as a query parameter. Payment gateway URLs for the two environments are: Sandbox: [https://sandbox-payments.montonio.com](https://sandbox-payments.montonio.com) Production: [https://payments.montonio.com](https://payments.montonio.com) Example url with payment\_token parameter: ```console https://payments.montonio.com?payment_token=eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJhbW91bnQiOjEwLCJjdXJyZW5jeSI6IkVVUiIsImFjY2Vzc19rZXkiOiJtZXJjaGFudF9hY2Nlc3Nfa2V5IiwibWVyY2hhbnRfcmVmZXJlbmNlIjoiU082NjExMjMiLCJtZXJjaGFudF9yZXR1cm5fdXJsIjoiaHR0cHM6Ly9tb250b25pby5jb20vb3JkZXJzLzI3NzMxNzczL3RoYW5rX3lvdSIsIm1lcmNoYW50X25vdGlmaWNhdGlvbl91cmwiOiJodHRwczovL21vbnRvbmlvLmNvbS9vcmRlcnMvcGF5bWVudF93ZWJob29rIiwicGF5bWVudF9pbmZvcm1hdGlvbl91bnN0cnVjdHVyZWQiOiJQYXltZW50IGZvciBvcmRlciBTTzY2MTEyMyIsInByZXNlbGVjdGVkX2FzcHNwIjoiTEhWQkVFMjIiLCJwcmVzZWxlY3RlZF9sb2NhbGUiOiJldCIsImNoZWNrb3V0X2VtYWlsIjoidGVzdC1jdXN0b21lckBtb250b25pby5jb20iLCJpYXQiOjE2MDEwMjA4MjUsImV4cCI6MTYwMTAyMTQyNX0.RfRVHklL7irHGN309AYRTMOXnq6UWYT2Mxb42oMh4JY ``` ## Validating the Payment ### Redirect Back to the Merchant Once the customer completes the payment, they will be redirected back to the `merchant_return_url` that you set in the original payment token with a new `payment_token` appended to the URL as a query parameter. [Validate the contents](#validating-the-returned-payment-token) and the signature of this token to confirm the order. Example return URL: ```console https://montonio.com/orders/27731773/thank_you?payment_token=eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJhbW91bnQiOiIxMC4wMCIsImFjY2Vzc19rZXkiOiJtZXJjaGFudF9hY2Nlc3Nfa2V5IiwibWVyY2hhbnRfcmVmZXJlbmNlIjoiU082NjExMjMiLCJzdGF0dXMiOiJmaW5hbGl6ZWQiLCJpYXQiOjE2MDEwMjQxNzcsImV4cCI6MTYwMTAzODU3N30.bJIPBK6ioiqkqjlQwV4F7YDrfNhhLzdSN4IpHoxXAw0 ``` ### Webhook Notification Once you set the `merchant_notification_url` parameter in the original payment token, we will send a `POST` request to this URL with a new `payment_token` appended to it as a query parameter. [Validate the contents](#validating-the-returned-payment-token) and the signature of this token to confirm the order. :::note Whitelist / allowlist the following IPs to receive webhook notifications: `35.156.245.42` and `35.156.159.169` ::: ### Validating the Returned Payment Token The `payment_token` that is appended to the `merchant_return_url` when redirecting back to the merchant or to the `merchant_notification_url` when sending a webhook notification needs to be validated. The token is signed with your `Secret Key`. On the code panel you can see examples of validating the token. Show / Hide Parameters Headers | Key | Type | Description | | --- | -------- | --------------------- | | alg | `string` | Always set to `HS256` | | typ | `string` | Always set to `JWT` | Payload | Key | Type | Description | | --------------------- | -------- | ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | | amount | `number` | Payment amount (up to 2 decimal places). | | access\_key | `string` | Your `Access Key` obtained from the Partner System. | | merchant\_reference | `string` | The order reference number you provided in the initial payment token. | | status | `string` | Payment status. Only consider `finalized` as the correct status for a completed payment. | | payment\_uuid | `string` | The payment's UUID in Montonio. | | customer\_iban | `string` | The customer's IBAN. If the payment has not been finalized or if it was a card payment, the value will be `null`. The value will also be `null` if the customer has paid with their Revolut account. | | payment\_method\_name | `string` | Friendly name of the payment method used. | | exp | `number` | Expiration time of the token in Unix time. | | iat | `number` | Issuing time of the token in Unix time. | Show / Hide Code Examples ```javascript /* * We recommend using the jsonwebtoken package to verify * Json Web Tokens. You can install it with npm: * > npm install jsonwebtoken * More information can be found at * https://www.npmjs.com/package/jsonwebtoken */ const jwt = require('jsonwebtoken'); // fetched from the URL const payment_token = 'eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJhbW91bnQiOiIxMC4wMCIsImFjY2Vzc19rZXkiOiJtZXJjaGFudF9hY2Nlc3Nfa2V5IiwibWVyY2hhbnRfcmVmZXJlbmNlIjoiU082NjExMjMiLCJzdGF0dXMiOiJmaW5hbGl6ZWQiLCJpYXQiOjE2MDEwMjQxNzcsImV4cCI6MTYwMTAzODU3N30.bJIPBK6ioiqkqjlQwV4F7YDrfNhhLzdSN4IpHoxXAw0'; // original order ID passed to merchant_reference const orderID = 'SO661123'; const decoded = jwt.verify(payment_token, 'merchant_secret_key'); if ( decoded.access_key === 'merchant_access_key' && decoded.merchant_reference === orderID && decoded.status === 'finalized' ) { // payment completed } else { // payment not completed } ``` ```php composer require firebase/php-jwt * More information can be found at * https://github.com/firebase/php-jwt */ use \Firebase\JWT\JWT; // fetched from the URL $payment_token = 'eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJhbW91bnQiOiIxMC4wMCIsImFjY2Vzc19rZXkiOiJtZXJjaGFudF9hY2Nlc3Nfa2V5IiwibWVyY2hhbnRfcmVmZXJlbmNlIjoiU082NjExMjMiLCJzdGF0dXMiOiJmaW5hbGl6ZWQiLCJpYXQiOjE2MDEwMjQxNzcsImV4cCI6MTYwMTAzODU3N30.bJIPBK6ioiqkqjlQwV4F7YDrfNhhLzdSN4IpHoxXAw0'; // original order ID passed to merchant_reference $orderID = 'SO661123'; $decoded = Firebase\JWT\JWT::decode( $payment_token, 'merchant_secret_key', array('HS256') ); if ( $decoded->access_key === 'merchant_access_key' && $decoded->merchant_reference === $orderID && $decoded->status === 'finalized' ) { // payment completed } else { // payment not completed } ?> ``` ```python ''' We recommend using the PyJWT package to verify Json Web Tokens. You can install it with pip: > pip3 install PyJWT More information can be found at https://pyjwt.readthedocs.io/en/latest/ ''' import jwt # fetched from the URL payment_token = 'eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJhbW91bnQiOiIxMC4wMCIsImFjY2Vzc19rZXkiOiJtZXJjaGFudF9hY2Nlc3Nfa2V5IiwibWVyY2hhbnRfcmVmZXJlbmNlIjoiU082NjExMjMiLCJzdGF0dXMiOiJmaW5hbGl6ZWQiLCJpYXQiOjE2MDEwMjQxNzcsImV4cCI6MTYwMTAzODU3N30.bJIPBK6ioiqkqjlQwV4F7YDrfNhhLzdSN4IpHoxXAw0' # original order ID passed to merchant_reference orderID = 'SO661123' try: decoded = jwt.decode( payment_token, 'merchant_secret_key', algorithms=['HS256'] ) except jwt.exceptions.InvalidSignatureError as identifier: pass # Token validation failed if ( decoded['access_key'] == 'merchant_access_key' and decoded['merchant_reference'] == orderID and decoded['status'] == 'finalized' ): pass # payment completed else: pass # payment not completed ``` ## Displaying the List of Available Banks To allow the customer to choose their bank in your checkout you need to fetch the list of available banks from our API. The selected bank's BIC must then be passed to the `preselected_aspsp` parameter in the initial payment token as described [here](#generating-the-payment-token). You can get the list of banks from the API endpoint `GET /v2/merchants/payment_methods`. The endpoint requires a JWT in the `Authorization` header as a bearer token and returns all available payment methods grouped by country. If you also use Stripe card payments through Montonio, you can set the value of `preselected_aspsp` to `CARD` in order to direct your customer through the card payment flow. Here are the API base URLs for our environments: Sandbox environment: [https://api.sandbox-payments.montonio.com/pis](https://api.sandbox-payments.montonio.com/pis) Production environment: [https://api.payments.montonio.com/pis](https://api.payments.montonio.com/pis) :::note We recommend caching the list of banks to avoid too many unnecessary requests to our API. ::: ### Generating the Token The endpoint requires a JWT in the `Authorization` header. The token must contain your `Access Key` and be signed with your `Secret Key` using HMAC SHA256 (HS256). The exact implementation of how to generate the JWT varies by programming language and you can see some examples on the code panel. Show / Hide Parameters Headers | Key | Required | Type | Description | | --- | -------- | -------- | ---------------------- | | alg | yes | `string` | Must be set to `HS256` | | typ | yes | `string` | Must be set to `JWT` | Payload | Key | Required | Type | Description | | ----------- | -------- | -------- | ------------------------------------------------------------------------------------------------- | | access\_key | yes | `string` | Your `Access Key` obtained from the Partner System. | | exp | yes | `number` | Expiration time of the token in Unix time. Set that to 1 hour from the time of issuing the token. | Show / Hide Code Examples ```javascript /** * We recommend using the jsonwebtoken package to generate * Json Web Tokens. You can install it with npm: * > npm install jsonwebtoken * More information can be found at * https://www.npmjs.com/package/jsonwebtoken */ const jwt = require('jsonwebtoken'); const payload = { access_key: 'merchant_access_key' }; const token = jwt.sign( payload, 'merchant_secret_key', { algorithm: 'HS256', expiresIn: '1h' } ); console.log(token); // eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJhY2Nlc3Nfa2V5IjoibWVyY2hhbnRfYWNjZXNzX2tleSIsImlhdCI6MTYwMzcxMTQ3NSwiZXhwIjoxNjAzNzE1MDc1fQ.UYwRQXykcIVNzIjni3icf_FBbxSXZ_m-2SsFfz3zjBs ``` ```php composer require firebase/php-jwt * More information can be found at * https://github.com/firebase/php-jwt */ use \Firebase\JWT\JWT; $payment_data = array( 'access_key' => 'merchant_access_key', 'iat' => time(), 'exp' => time() + (60 * 60) ); $payment_token = \Firebase\JWT\JWT::encode($payment_data, 'merchant_secret_key', 'HS256'); echo $payment_token; // eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJhY2Nlc3Nfa2V5IjoibWVyY2hhbnRfYWNjZXNzX2tleSIsImlhdCI6MTYwMzcxMTQ3NSwiZXhwIjoxNjAzNzE1MDc1fQ.UYwRQXykcIVNzIjni3icf_FBbxSXZ_m-2SsFfz3zjBs ?> ``` ```python ''' We recommend using the PyJWT package to generate Json Web Tokens. You can install it with pip: > pip3 install PyJWT datetime More information can be found at https://pyjwt.readthedocs.io/en/latest/ ''' import jwt from datetime import datetime, timedelta, timezone payment_data = { 'access_key': 'merchant_access_key', 'iat': datetime.now(timezone.utc), 'exp': datetime.now(timezone.utc) + timedelta(hours=1) } payment_token = jwt.encode( payment_data, 'merchant_secret_key', algorithm='HS256' ).decode('utf-8') print(payment_token) # eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJhY2Nlc3Nfa2V5IjoibWVyY2hhbnRfYWNjZXNzX2tleSIsImlhdCI6MTYwMzcxMTQ3NSwiZXhwIjoxNjAzNzE1MDc1fQ.UYwRQXykcIVNzIjni3icf_FBbxSXZ_m-2SsFfz3zjBs ``` ### GET /v2/merchants/payment\_methods > Headers for the request: ```shell Authorization: Bearer eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJhY2Nlc3Nfa2V5IjoibWVyY2hhbnRfYWNjZXNzX2tleSIsImlhdCI6MTYwMzcxMTQ3NSwiZXhwIjoxNjAzNzE1MDc1fQ.UYwRQXykcIVNzIjni3icf_FBbxSXZ_m-2SsFfz3zjBs ``` > Example request ```shell curl -X GET \ '[BASE_URL]/v2/merchants/payment_methods' \ -H 'Authorization: Bearer eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJhY2Nlc3Nfa2V5IjoiOTZlNjhlZDEtMDkzOC00NTE0LWFkZDEtYmE1MGE0NmI3YWZkIiwiaWF0IjoxNjAzNzE1MjczLCJleHAiOjE2MDM3MTg4NzN9.LpSPYEtkRd5Ze4RZoeN8rRs6hzNP1cqw_Th8x4oRCXo' ``` > Example response: Show / Hide Response Data ```json { "EE": { "supported_currencies": [ "EUR" ], "payment_methods": [ { "code": "HABAEE2X", "name": "Swedbank Eesti", "logo_url": "https://public.montonio.com/images/aspsps_logos/swedbank.png", "supported_currencies": [ "EUR" ] }, { "code": "EEUHEE2X", "name": "SEB Eesti", "logo_url": "https://public.montonio.com/images/aspsps_logos/seb.png", "supported_currencies": [ "EUR" ] }, { "code": "LHVBEE22", "name": "LHV", "logo_url": "https://public.montonio.com/images/aspsps_logos/lhv.png", "supported_currencies": [ "EUR" ] }, { "code": "RIKOEE22", "name": "Luminor Eesti", "logo_url": "https://public.montonio.com/images/aspsps_logos/luminor.png", "supported_currencies": [ "EUR" ] }, { "code": "EKRDEE22", "name": "Coop Pank", "logo_url": "https://public.montonio.com/images/aspsps_logos/coop.png", "supported_currencies": [ "EUR" ] }, { "code": "PARXEE22", "name": "Citadele Eesti", "logo_url": "https://public.montonio.com/images/aspsps_logos/citadele.png", "supported_currencies": [ "EUR" ] }, { "code": "RVUALT2V", "name": "Revolut", "logo_url": "https://public.montonio.com/images/aspsps_logos/revolut.png", "supported_currencies": [ "EUR", "PLN" ] }, { "code": "CARD", "name": "Visa / Mastercard", "logo_url": "https://public.montonio.com/images/aspsps_logos/visa.png", "supported_currencies": [ "EUR", "PLN" ] } ] }, "FI": { "supported_currencies": [ "EUR" ], "payment_methods": [ { "code": "OKOYFIHH", "name": "OP", "logo_url": "https://public.montonio.com/images/aspsps_logos/op.png", "supported_currencies": [ "EUR" ] }, { "code": "NDEAFIHH", "name": "Nordea", "logo_url": "https://public.montonio.com/images/aspsps_logos/nordea.png", "supported_currencies": [ "EUR" ] }, { "code": "DABAFIHH", "name": "Danske Bank", "logo_url": "https://public.montonio.com/images/aspsps_logos/danske.png", "supported_currencies": [ "EUR" ] }, { "code": "ITELFIHH", "name": "Säästöpankki", "logo_url": "https://public.montonio.com/images/aspsps_logos/saastopankki.png", "supported_currencies": [ "EUR" ] }, { "code": "POPFFI22", "name": "POP Pankki", "logo_url": "https://public.montonio.com/images/aspsps_logos/pop.png", "supported_currencies": [ "EUR" ] }, { "code": "ITELFIHH", "name": "Oma Säästöpankki", "logo_url": "https://public.montonio.com/images/aspsps_logos/omasp.png", "supported_currencies": [ "EUR" ] }, { "code": "SBANFIHH", "name": "S-Pankki", "logo_url": "https://public.montonio.com/images/aspsps_logos/s-pankki.png", "supported_currencies": [ "EUR" ] }, { "code": "AABAFI22", "name": "Alandsbanken", "logo_url": "https://public.montonio.com/images/aspsps_logos/alandsbanken-fi.png", "supported_currencies": [ "EUR" ] }, { "code": "RVUALT2V", "name": "Revolut", "logo_url": "https://public.montonio.com/images/aspsps_logos/revolut.png", "supported_currencies": [ "EUR", "PLN" ] }, { "code": "CARD", "name": "Visa / Mastercard", "logo_url": "https://public.montonio.com/images/aspsps_logos/visa.png", "supported_currencies": [ "EUR", "PLN" ] } ] }, "LV": { "supported_currencies": [ "EUR" ], "payment_methods": [ { "code": "HABALV22", "name": "Swedbank Latvija", "logo_url": "https://public.montonio.com/images/aspsps_logos/swedbank.png", "supported_currencies": [ "EUR" ] }, { "code": "UNLALV2X", "name": "SEB Latvija", "logo_url": "https://public.montonio.com/images/aspsps_logos/seb.png", "supported_currencies": [ "EUR" ] }, { "code": "PARXLV22", "name": "Citadele Latvija", "logo_url": "https://public.montonio.com/images/aspsps_logos/citadele.png", "supported_currencies": [ "EUR" ] }, { "code": "RIKOLV2X", "name": "Luminor Latvija", "logo_url": "https://public.montonio.com/images/aspsps_logos/luminor.png", "supported_currencies": [ "EUR" ] }, { "code": "RVUALT2V", "name": "Revolut", "logo_url": "https://public.montonio.com/images/aspsps_logos/revolut.png", "supported_currencies": [ "EUR", "PLN" ] }, { "code": "CARD", "name": "Visa / Mastercard", "logo_url": "https://public.montonio.com/images/aspsps_logos/visa.png", "supported_currencies": [ "EUR", "PLN" ] } ] }, "LT": { "supported_currencies": [ "EUR" ], "payment_methods": [ { "code": "HABALT22", "name": "Swedbank Lietuva", "logo_url": "https://public.montonio.com/images/aspsps_logos/swedbank.png", "supported_currencies": [ "EUR" ] }, { "code": "CBVILT2X", "name": "SEB Lietuva", "logo_url": "https://public.montonio.com/images/aspsps_logos/seb.png", "supported_currencies": [ "EUR" ] }, { "code": "AGBLLT2X", "name": "Luminor Lietuva", "logo_url": "https://public.montonio.com/images/aspsps_logos/luminor.png", "supported_currencies": [ "EUR" ] }, { "code": "CBSBLT26", "name": "Šiaulių bankas", "logo_url": "https://public.montonio.com/images/aspsps_logos/siauliu.png", "supported_currencies": [ "EUR" ] }, { "code": "MDBALT22", "name": "Medicinos bankas", "logo_url": "https://public.montonio.com/images/aspsps_logos/medicinos.png", "supported_currencies": [ "EUR" ] }, { "code": "INDULT2X", "name": "Citadele Lietuva", "logo_url": "https://public.montonio.com/images/aspsps_logos/citadele.png", "supported_currencies": [ "EUR" ] }, { "code": "RVUALT2V", "name": "Revolut", "logo_url": "https://public.montonio.com/images/aspsps_logos/revolut.png", "supported_currencies": [ "EUR", "PLN" ] }, { "code": "CARD", "name": "Visa / Mastercard", "logo_url": "https://public.montonio.com/images/aspsps_logos/visa.png", "supported_currencies": [ "EUR", "PLN" ] } ] }, "PL": { "supported_currencies": [ "PLN" ], "payment_methods": [ { "code": "BPKOPLPW", "name": "PKO Bank Polski", "logo_url": "https://public.montonio.com/images/aspsps_logos/pko-polski.png", "supported_currencies": [ "PLN" ] }, { "code": "PKOPPLPW", "name": "Bank Pekao", "logo_url": "https://public.montonio.com/images/aspsps_logos/pekao.png", "supported_currencies": [ "PLN" ] }, { "code": "BREXPLPW", "name": "mBank", "logo_url": "https://public.montonio.com/images/aspsps_logos/mbank.png", "supported_currencies": [ "PLN" ] }, { "code": "WBKPPLPP", "name": "Santander", "logo_url": "https://public.montonio.com/images/aspsps_logos/santander.png", "supported_currencies": [ "PLN" ] }, { "code": "INGBPLPW", "name": "Ing", "logo_url": "https://public.montonio.com/images/aspsps_logos/ing.png", "supported_currencies": [ "PLN" ] }, { "code": "ALBPPLPW", "name": "Alior", "logo_url": "https://public.montonio.com/images/aspsps_logos/alior.png", "supported_currencies": [ "PLN" ] }, { "code": "PPABPLPK", "name": "BNP Paribas", "logo_url": "https://public.montonio.com/images/aspsps_logos/bnp-paribas.png", "supported_currencies": [ "PLN" ] }, { "code": "BIGBPLPW", "name": "Millennium Bank", "logo_url": "https://public.montonio.com/images/aspsps_logos/millennium.png", "supported_currencies": [ "PLN" ] }, { "code": "IBNKPAPA", "name": "Inteligo", "logo_url": "https://public.montonio.com/images/aspsps_logos/inteligo.png", "supported_currencies": [ "PLN" ] }, { "code": "AGRIPLPR", "name": "Crédit Agricole", "logo_url": "https://public.montonio.com/images/aspsps_logos/credit-agricole.png", "supported_currencies": [ "PLN" ] }, { "code": "RVUALT2V", "name": "Revolut", "logo_url": "https://public.montonio.com/images/aspsps_logos/revolut.png", "supported_currencies": [ "EUR", "PLN" ] }, { "code": "CARD", "name": "Visa / Mastercard", "logo_url": "https://public.montonio.com/images/aspsps_logos/visa.png", "supported_currencies": [ "EUR", "PLN" ] } ] } } ``` The endpoint returns the list of available banks for a merchant. URL Sandbox: [https://api.sandbox-payments.montonio.com/pis/v2/merchants/payment\_methods](https://api.sandbox-payments.montonio.com/pis/v2/merchants/payment_methods) Production: [https://api.payments.montonio.com/pis/v2/merchants/payment\_methods](https://api.payments.montonio.com/pis/v2/merchants/payment_methods) Headers | Key | Required | Value | | ------------- | -------- | --------------------- | | Authorization | yes | `Bearer [your_token]` | ## GET /v2/merchants/payments The endpoint returns a payment\_token containing details about the payment. See Validating the Returned Payment Token for details on how to decode and verify the token. URL Sandbox: [https://api.sandbox-payments.montonio.com/pis/v2/merchants/payments](https://api.sandbox-payments.montonio.com/pis/v2/merchants/payments) Production: [https://api.payments.montonio.com/pis/v2/merchants/payments](https://api.payments.montonio.com/pis/v2/merchants/payments) Headers | Key | Required | Value | | ------------- | -------- | --------------------- | | Authorization | yes | `Bearer [your_token]` | Query Parameters | Key | Required | Value | | ------------------- | -------- | --------------------------------------------------------------------- | | merchant\_reference | yes | The order reference number you provided in the initial payment token. | Example header for the request: ```shell Authorization: Bearer eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJhY2Nlc3Nfa2V5IjoibWVyY2hhbnRfYWNjZXNzX2tleSIsImlhdCI6MTYwMzcxMTQ3NSwiZXhwIjoxNjAzNzE1MDc1fQ.UYwRQXykcIVNzIjni3icf_FBbxSXZ_m-2SsFfz3zjBs ``` Example request: ```shell curl -X GET \ '[BASE_URL]/v2/merchants/payments?merchant_reference=SO661123' \ -H 'Authorization: Bearer eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJhY2Nlc3Nfa2V5IjoiOTZlNjhlZDEtMDkzOC00NTE0LWFkZDEtYmE1MGE0NmI3YWZkIiwiaWF0IjoxNjAzNzE1MjczLCJleHAiOjE2MDM3MTg4NzN9.LpSPYEtkRd5Ze4RZoeN8rRs6hzNP1cqw_Th8x4oRCXo' ``` Example response + [decoded](https://jwt.io) payload: ```json { "payment_token": "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJhbW91bnQiOiIxMC4wMCIsImFjY2Vzc19rZXkiOiJtZXJjaGFudF9hY2Nlc3Nfa2V5IiwibWVyY2hhbnRfcmVmZXJlbmNlIjoiU082NjExMjMiLCJzdGF0dXMiOiJmaW5hbGl6ZWQiLCJpYXQiOjE2MDEwMjQxNzcsImV4cCI6MTYwMTAzODU3N30.bJIPBK6ioiqkqjlQwV4F7YDrfNhhLzdSN4IpHoxXAw0" } ``` ```json { "amount": "10.00", "access_key": "merchant_access_key", "merchant_reference": "SO661123", "status": "finalized", "iat": 1601024177, "exp": 1601038577 } ``` Response Statuses | Value | Description | | ----------- | ------------------------------------------------------------------------------------------------------------ | | `abandoned` | The payment was not completed by the customer. | | `pending` | The payment has not been completed and will transition to abandoned status. | | `finalized` | The payment has been completed by the customer's bank, and will, or has, arrive(d) in the receiving account. | [Head back to Montonio](https://www.montonio.com) --- # Shipping URL: /api/shipping Welcome to the Montonio Shipping API Developer Documentation. Here you can find instructions on how to integrate with **Montonio Shipping**. # Production Only To access the shipping API, you will need to use production keys. Production keys will become available once you sign an agreement for either one of our services. For the shipping API specifically, production keys can also be used for testing purposes since no real costs are involved without sending actual packages. ## Activating Shipping Providers In order to be able to pass data to shipping providers, Montonio also requires credentials to their respective APIs. In order to activate a shipping provider, navigate to the Shipping page and select the Providers tab. Under the Providers tab, you can select which provider to enable for your store and enter their respective credentials. :::note If you do not have credentials for a shipping provider, you can register with their respective e-service in order to obtain them. For more info, contact the specific service provider. ::: # Using the API The API base URL for all endpoints is `https://api.shipping.montonio.com`. All the endpoints provided in this documentation require authorization in the form of a JSON Web Token (JWT) in the `Authorization` header as a bearer token. ## Generating the Token The JWT used for authorization must contain your `Access Key` and be signed with your `Secret Key` using HMAC SHA256 (HS256). The exact implementation of how to generate the JWT varies by programming language and you can see some examples on the code panel. :::note We recommend using popular community maintained libraries for JWT generation. You can browse the libraries for your programming language on the [jwt.io](https://jwt.io) website. ::: Show / Hide Parameters Headers | Key | Required | Type | Description | | --- | -------- | -------- | ---------------------- | | alg | yes | `string` | Must be set to `HS256` | | typ | yes | `string` | Must be set to `JWT` | Payload | Key | Required | Type | Description | | ----------- | -------- | -------- | ------------------------------------------------------------------------------------------------- | | access\_key | yes | `string` | Your `Access Key` obtained from the Partner System. | | exp | yes | `number` | Expiration time of the token in Unix time. Set that to 1 hour from the time of issuing the token. | Show / Hide Code Examples ```javascript /** * We recommend using the jsonwebtoken package to generate * Json Web Tokens. You can install it with npm: * > npm install jsonwebtoken * More information can be found at * https://www.npmjs.com/package/jsonwebtoken */ const jwt = require('jsonwebtoken'); const payload = { access_key: 'merchant_access_key' } const token = jwt.sign( payload, 'merchant_secret_key', { algorithm: 'HS256', expiresIn: '1h' } ); console.log(token); // eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJhY2Nlc3Nfa2V5IjoibWVyY2hhbnRfYWNjZXNzX2tleSIsImlhdCI6MTYwMzcxMTQ3NSwiZXhwIjoxNjAzNzE1MDc1fQ.UYwRQXykcIVNzIjni3icf_FBbxSXZ_m-2SsFfz3zjBs ``` ```php composer require firebase/php-jwt * More information can be found at * https://github.com/firebase/php-jwt */ use \Firebase\JWT\JWT; $payment_data = array( 'access_key' => 'merchant_access_key', 'iat' => time(), 'exp' => time() + (60 * 60) ); $payment_token = \Firebase\JWT\JWT::encode($payment_data, 'merchant_secret_key', 'HS256'); echo $payment_token; // eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJhY2Nlc3Nfa2V5IjoibWVyY2hhbnRfYWNjZXNzX2tleSIsImlhdCI6MTYwMzcxMTQ3NSwiZXhwIjoxNjAzNzE1MDc1fQ.UYwRQXykcIVNzIjni3icf_FBbxSXZ_m-2SsFfz3zjBs ?> ``` ```python ''' We recommend using the PyJWT package to generate Json Web Tokens. You can install it with pip: > pip3 install PyJWT datetime More information can be found at https://pyjwt.readthedocs.io/en/latest/ ''' import jwt from datetime import datetime, timedelta, timezone payment_data = { 'access_key': 'merchant_access_key', 'iat': datetime.now(timezone.utc), 'exp': datetime.now(timezone.utc) + timedelta(hours=1) } payment_token = jwt.encode( payment_data, 'merchant_secret_key', algorithm='HS256' ).decode('utf-8') print(payment_token) # eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJhY2Nlc3Nfa2V5IjoibWVyY2hhbnRfYWNjZXNzX2tleSIsImlhdCI6MTYwMzcxMTQ3NSwiZXhwIjoxNjAzNzE1MDc1fQ.UYwRQXykcIVNzIjni3icf_FBbxSXZ_m-2SsFfz3zjBs ``` ## Displaying the List of Available Pickup Points > Example request header: ```shell Authorization: Bearer eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJhY2Nlc3Nfa2V5IjoibWVyY2hhbnRfYWNjZXNzX2tleSIsImlhdCI6MTYwMzcxMTQ3NSwiZXhwIjoxNjAzNzE1MDc1fQ.UYwRQXykcIVNzIjni3icf_FBbxSXZ_m-2SsFfz3zjBs ``` > Example request ```shell curl -X GET \ 'https://api.shipping.montonio.com/pickup-points' \ -H 'Authorization: Bearer eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJhY2Nlc3Nfa2V5IjoiOTZlNjhlZDEtMDkzOC00NTE0LWFkZDEtYmE1MGE0NmI3YWZkIiwiaWF0IjoxNjAzNzE1MjczLCJleHAiOjE2MDM3MTg4NzN9.LpSPYEtkRd5Ze4RZoeN8rRs6hzNP1cqw_Th8x4oRCXo' ``` Show / Hide Response Data ```json { "EE": { "providers": { "omniva": { "post_office": [ { "uuid": "23219ba9-e4af-4416-acfd-938cff0296e8", "name": "Aseri postipunkt", "country": "EE", "type": "post_office", "provider_name": "omniva", "region": "Lääne-Viru maakond", "locality": "Viru-Nigula vald" }, { "uuid": "542e3e42-79dc-42e6-8a50-9d90fc09da13", "name": "Avinurme postipunkt", "country": "EE", "type": "post_office", "provider_name": "omniva", "region": "Jõgeva maakond", "locality": "Mustvee vald" } ], "parcel_machine": [ { "uuid": "5a3239e8-9ce6-439c-8a3b-f8d8f3611149", "name": "Ahtme Maxima XX pakiautomaat", "country": "EE", "type": "parcel_machine", "provider_name": "omniva", "region": "Ida-Viru maakond", "locality": "Kohtla-Järve linn" }, { "uuid": "c479703b-9632-4704-b962-1742ef8609bb", "name": "Antsla Coop Konsumi pakiautomaat", "country": "EE", "type": "parcel_machine", "provider_name": "omniva", "region": "Võru maakond", "locality": "Antsla vald" } ] }, "itella": { "parcel_machine": [ { "uuid": "ea15bc94-e6c2-467d-b537-740fdf199991", "name": "Tammiste Konsum (valge)", "country": "EE", "type": "parcel_machine", "provider_name": "itella", "region": null, "locality": "Tammiste" }, { "uuid": "9845fe06-e0cd-4702-aa82-85c169f654c2", "name": "Jõhvi Pargi keskus (valge)", "country": "EE", "type": "parcel_machine", "provider_name": "itella", "region": null, "locality": "Jõhvi" } ] } } }, "LV": { "providers": { "omniva": { "parcel_machine": [ { "uuid": "1359dcb4-9933-4c6d-8c71-8a6118cd9d2d", "name": "Aizkraukles T/C Iga pakomāts", "country": "LV", "type": "parcel_machine", "provider_name": "omniva", "region": "Aizkraukles novads", "locality": "Aizkraukle" } ] } } }, "LT": { "providers": { "omniva": { "parcel_machine": [ { "uuid": "f97d1d8c-6aa3-4da4-a44e-25136da64efb", "name": "Alytaus IKI Jaunimo paštomatas", "country": "LT", "type": "parcel_machine", "provider_name": "omniva", "region": "Alytaus apskr.", "locality": "Alytaus m. sav." } ] } } }, "FI": { "providers": { "itella": { "parcel_machine": [ { "uuid": "e33d7914-5149-4863-865a-5d33abc43ac8", "name": "R-kioski Pohjois-Haaga", "country": "FI", "type": "parcel_machine", "provider_name": "itella", "region": null, "locality": "HELSINKI" } ] } } } } ``` `GET /pickup-points` In order to use a pickup point service (parcel machines or post offices), you need to fetch the list of available pickup points from our API. Each pickup point has a unique UUID string that must be included when creating a shipment using that pickup point. The endpoint returns pickup points grouped by country, provider and type (parcel machine or post office). Note that only the pickup points from providers that have been activated in the partner system will be returned. :::note We recommend caching the list of pickup points to avoid too many unnecessary requests to our API. It is recommended to update pickup points once every 24 hours. ::: URL `https://api.shipping.montonio.com/pickup-points` Headers | Key | Required | Value | | ------------- | -------- | --------------------- | | Authorization | yes | `Bearer [your_token]` | ## Creating a shipment `POST /shipments` This endpoint is used to create a shipment in the Montonio Partner System and register it with the given service provider. This can be done at any point after the customer has completed their order. To create a shipment without waiting for response, use `/shipments/create-async` endpoint instead. This will immediately return an empty body with the status code 201 and attempt to register the shipment in the background. This is useful if you want to minimalize the wait time for customer after completing checkout. > Example request header:: ```shell Authorization: Bearer eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJhY2Nlc3Nfa2V5IjoibWVyY2hhbnRfYWNjZXNzX2tleSIsImlhdCI6MTYwMzcxMTQ3NSwiZXhwIjoxNjAzNzE1MDc1fQ.UYwRQXykcIVNzIjni3icf_FBbxSXZ_m-2SsFfz3zjBs ``` Show / Hide Example Request ```shell curl -X POST \ 'https://api.shipping.montonio.com/shipments' \ -H 'Authorization: Bearer eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJhY2Nlc3Nfa2V5IjoiOTZlNjhlZDEtMDkzOC00NTE0LWFkZDEtYmE1MGE0NmI3YWZkIiwiaWF0IjoxNjAzNzE1MjczLCJleHAiOjE2MDM3MTg4NzN9.LpSPYEtkRd5Ze4RZoeN8rRs6hzNP1cqw_Th8x4oRCXo' -d '{ "shipping_method": "dpd_parcel_machines", "pickup_point_uuid": "736750c9-e793-4ef1-b923-0268dd6492fd", "merchant_reference": "95", "sender_name": "Montonio OÜ", "sender_phone_country": "372", "sender_phone_number": "55512345", "sender_street_address_1": "Test address 123", "sender_street_address_2": "45", "sender_locality": "Tallinn", "sender_region": "Harjumaa", "sender_postal_code": "12345", "sender_country": "EE", "shipping_first_name": "John", "shipping_last_name": "Smith", "shipping_company": "Test Company OÜ", "shipping_street_address_1": "Test street 234", "shipping_street_address_2": "56-B", "shipping_locality": "Tartu", "shipping_region": "Tartumaa", "shipping_postal_code": "11111", "shipping_country": "EE", "shipping_email": "test@example.com", "shipping_phone_country": "372", "shipping_phone_number": "5555555", "billing_first_name": "John", "billing_last_name": "Smith", "billing_company": "Test Company OÜ", "billing_street_address_1": "Test street 234", "billing_street_address_2": "56-B", "billing_locality": "Tartu", "billing_region": "Tartumaa", "billing_postal_code": "11111", "billing_country": "EE", "billing_email": "test@example.com", "billing_phone_country": "372", "billing_phone_number": "5555555", "currency": "EUR", "shipping_total": 1.50, "total": 25.90, "parcels": [ { "weight": 1.02 } ] }' ``` > Example response: ```json { "uuid": "d682bfd5-6ea3-4b70-bb59-bc5b009dddd2", "shipping_method": { "uuid": "0980e92b-ab97-48d3-af3b-1aabc987b4d9", "identifier": "dpd_parcel_machines", "name": "DPD pickup points", "provider_name": "dpd", "type": "parcel_machine", "available_in_countries": [ "EE", "LV", "LT" ] }, "currency": "EUR", "shipping_total": "1.50", "total": "25.90", "billing_first_name": "John", "billing_last_name": "Smith", "billing_company": "Test Company OÜ", "billing_street_address_1": "Test street 234", "billing_street_address_2": "56-B", "billing_locality": "Tartu", "billing_region": "Tartumaa", "billing_postal_code": "11111", "billing_country": "EE", "billing_email": "test@example.com", "billing_phone_number": "5555555", "shipping_first_name": "John", "shipping_last_name": "Smith", "shipping_company": "Test Company OÜ", "shipping_street_address_1": "Test street 234", "shipping_street_address_2": "56-B", "shipping_locality": "Tartu", "shipping_region": "Tartumaa", "shipping_postal_code": "11111", "shipping_country": "EE", "shipping_email": "test@example.com", "shipping_phone_number": "5555555", "payment_method": null, "merchant_reference": "95", "sender_name": "Montonio Finance OÜ", "sender_phone_number": "55512345", "sender_street_address_1": "Test address 123", "sender_street_address_2": "45", "sender_locality": "Tallinn", "sender_region": "Harjumaa", "sender_postal_code": "12345", "sender_country": "EE", "error_reason": null, "duplicate_shipment_sort_order": 158 } ``` URL `https://api.shipping.montonio.com/shipments` `https://api.shipping.montonio.com/shipments/create-async` Show / Hide Parameters Headers | Key | Required | Value | | ------------- | -------- | --------------------- | | Authorization | yes | `Bearer [your_token]` | Body | Key | Required | Data type | Notes | Example Value | | ---------------------------- | -------- | --------- | ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | ---------------------------------------- | | merchant\_reference | yes | `string` | The order reference in the merchant's system (e.g. the order ID). Note that this will also be included on the shipping label. | `"1001"` | | sender\_name | yes | `string` | The company name for return address | `"Montonio Finance OÜ"` | | sender\_phone\_number | yes | `string` | The phone number of return addressee (without country code). Can be with country code if sender\_phone\_country is empty | `"55512345"` | | sender\_street\_address\_1 | yes | `string` | The first line of return street address | `"Test address 123"` | | sender\_locality | yes | `string` | The city or town for return address | `"Tallinn"` | | sender\_postal\_code | yes | `string` | The postal code for return address | `"12345"` | | sender\_country | yes | `string` | The two-letter code for return address country | `"EE"` | | shipping\_first\_name | yes | `string` | The first name from customer's shipping info | `"John"` | | shipping\_phone\_number | yes | `string` | The customer's shipping phone number (without country code). Can be with country code if shipping\_phone\_country is empty | `"55512345"` | | parcels | yes | `array` | An array of objects containing data for each parcel to be sent (should include exactly one object if sending whole order as one package), see below | `[{...}, {...}]` | | shipping\_method | no | `string` | A string value specifying which provider and method is being used. If not provided, will only create the shipment in Montonio Partner System, but won't register with provider. Currently accepted values: `omniva_parcel_machines`, `omniva_post_offices`, `omniva_courier`, `itella_parcel_machines`, `itella_post_offices`, `itella_courier`, `dpd_parcel_machines`, `dpd_courier`, `venipak_courier`, `venipak_parcel_shop`, `venipak_parcel_machines` | `"omniva_parcel_machines"` | | pickup\_point\_uuid | no | `string` | The unique id used to identify the pickup point on our end. Required if shipping method is not courier. | `"23219ba9-e4af-4416-acfd-938cff0296e8"` | | sender\_phone\_country | no | `string` | The country code of return addressee's phone | `"372"` | | sender\_street\_address\_2 | no | `string` | The second line of return street address | `"45"` | | sender\_region | no | `string` | The region for return address | `"Harjumaa"` | | shipping\_last\_name | no | `string` | The last name from customer's shipping info | `"Smith"` | | shipping\_company | no | `string` | The company name from cusomer's shipping info | `"Montonio Finance OÜ"` | | shipping\_street\_address\_1 | no | `string` | The first line from customer's shipping address. Required if sending via courier | `"Test address 123"` | | shipping\_street\_address\_2 | no | `string` | The second line from customer's shipping address | `"45"` | | shipping\_locality | no | `string` | The city or town from customer's shipping address. Required if sending via courier | `"Tallinn"` | | shipping\_region | no | `string` | The region from customer's shipping address | `"Harjumaa"` | | shipping\_postal\_code | no | `string` | The postal code from customer's shipping address. Required if sending via courier | `"12345"` | | shipping\_country | no | `string` | The two-letter country code representing customer's shipping country. Required if sending via courier | `"EE"` | | shipping\_email | no | `string` | The customer's shipping e-mail | `"test@example.com"` | | shipping\_phone\_country | no | `string` | The country code of customer's shipping phone number | `"372"` | | billing\_first\_name | no | `string` | The first name from customer's billing info | `"John"` | | billing\_last\_name | no | `string` | The last name from customer's billing info | `"Smith"` | | billing\_company | no | `string` | The company name from cusomer's billing info | `"Montonio Finance OÜ"` | | billing\_street\_address\_1 | no | `string` | The first line from customer's billing address | `"Test address 123"` | | billing\_street\_address\_2 | no | `string` | The second line from customer's billing address | `"45"` | | billing\_locality | no | `string` | The city or town from customer's billing address | `"Tallinn"` | | billing\_region | no | `string` | The region from customer's billing address | `"Harjumaa"` | | billing\_postal\_code | no | `string` | The postal code from customer's billing address | `"12345"` | | billing\_country | no | `string` | The two-letter country code representing customer's billing country | `"EE"` | | billing\_email | no | `string` | The customer's billing e-mail | `"test@example.com"` | | billing\_phone\_country | no | `string` | The country code of customer's billing phone number | `"372"` | | billing\_phone\_number | no | `string` | The customer's billing phone number (without country code). Can be with country code if billing\_phone\_country is empty | `"55512345"` | | currency | no | `string` | The three-letter currency code used for given order | `"EUR"` | | shipping\_total | no | `number` | The total shipping cost for given order (up to 2 decimal places) | `1.50` | | total | no | `number` | The total cost of the given order, including shipping (up to 2 decimal places) | `25.90` | Body: Parcel object | Key | Required | Data type | Notes | Example Value | | ------ | -------- | --------- | ----------------------------------------------------------------------------------------------------------------------------------------------------------- | ------------- | | weight | yes | number | Weight of parcel in kg (up to 2 decimal places). Can be 0 if unknown. Refer service providers' home pages for info on weight limits for different services. | `1.02` | :::note If there is an error when registering the shipment with the provider, the shipment will still be created in Montonio Partner System. There you can see the error message and duplicate the shipment to manually change data and try again. ::: ## Printing shipment labels `POST /shipments/label-from-store` This endpoint is used to print labels for one or more shipments that have been successfully registered with their respective shipping providers. It returns a download link to a PDF file containing all the shipping labels for specified shipments. > Example request header:: ```shell Authorization: Bearer eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJhY2Nlc3Nfa2V5IjoibWVyY2hhbnRfYWNjZXNzX2tleSIsImlhdCI6MTYwMzcxMTQ3NSwiZXhwIjoxNjAzNzE1MDc1fQ.UYwRQXykcIVNzIjni3icf_FBbxSXZ_m-2SsFfz3zjBs ``` > Example request ```shell curl -X POST \ 'https://api.shipping.montonio.com/shipments/label-from-store' \ -H 'Authorization: Bearer eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJhY2Nlc3Nfa2V5IjoiOTZlNjhlZDEtMDkzOC00NTE0LWFkZDEtYmE1MGE0NmI3YWZkIiwiaWF0IjoxNjAzNzE1MjczLCJleHAiOjE2MDM3MTg4NzN9.LpSPYEtkRd5Ze4RZoeN8rRs6hzNP1cqw_Th8x4oRCXo' -d '{ "merchant_references": [ "1001", "1002", "1005" ] }' ``` > Example response: ```json { "url": "https://s3.eu-central-1.amazonaws.com/data.tmp.montonio.com/labels-45adfe1f-0bc4-4fb4-ba5d-0d9299c7c809.pdf?X-Amz-Algorithm=AWS4-HMAC-SHA256&X-Amz-Credential=ASIATGBFH3FPJMSLH65C%2F20220502%2Feu-central-1%2Fs3%2Faws4_request&X-Amz-Date=20220502T131030Z&X-Amz-Expires=3600&X-Amz-SignedHeaders=host&X-Amz-Security-Token=IQoJb3JpZ2luX2VjEH0aDGV1LWNlbnRyYWwtMSJIMEYCIQDpitxXwQe9UEWEcNCd9ESdYjoX3VhYP%2BsyWXfLgxoz9gIhAMzz8X5KhNa%2BGY0fJvuhJkc6l3H1TVibCX2fzJU%2F3GQRKpgCCEYQAxoMMjE5MTIxNDQxMTE4IgywQpuao9j7vRC41wsq9QG0bSP6DkRE%2BkKssNrYdBnPzfBf27UI7nS4jJSBwJfW3TOeGGUTj9TkK39QiXeH1u6bx9gDWQMinmG4y%2FcHmcjumC%2FSLcPSnvDe6GFq4ppqnhMvhBhA07ekINO20u58RCuQfVokuL70YNvMCF%2FZHpgCqShxJj3mJFvSb%2BSW5lpHPCB9qs7g7pTDvGfhfmCc7NP4dNIvb657F%2FBI13enxRDzItbCfd3GgOcZ5Fx0lvyQLN1HhDcbyqG%2FaBQoJ3bNEPUH4vezjFwxr1yoUXNW8BhbX2veYPqkNxJVAVxB4wP6YisY4bLKtyB8X%2FQ9UbwXz%2Fq%2BYT36rzDDsL%2BTBjqZAYUrGee3YY4KP%2Fn1ENvHhzWHXEW4UX1LJE%2FMvews1%2B9njaduEctyrJaR4CbiQ5FiiOzZCsqCF8Za8hUp20p1ZGwVpe3p2ldkscCB1fuPDiGR0rNDk62iFq3lmCoF359BPdaGT1VbJsX6lxO0LBL5Ze5sbb%2FB6Qz%2FO3ITDplJMvZUu0muGaAyDHTFMDzAadVB75kX%2FRKDPO9OVQ%3D%3D&X-Amz-Signature=96fe358ca057adce8919c5702a055e207220c8e733dd7176357355f8cf2d4743" } ``` URL `https://api.shipping.montonio.com/shipments/label-from-store` Headers | Key | Required | Value | | ------------- | -------- | --------------------- | | Authorization | yes | `Bearer [your_token]` | Body | Key | Required | Data type | Notes | Example Value | | -------------------- | -------- | --------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------ | ------------------ | | merchant\_references | yes | `array` | An array of related orders' reference strings in your store. These will be used to match partner system shipments to your store orders when printing labels. | `["1001", "1005"]` | ## Registering a webhook `PATCH /stores/store-webhook` This endpoint is used to register a webhook we can call on certain events. Currently it is used for two events: when a shipment is successfully registered with shipping provider and when its label has been printed. > Example request header:: ```shell Authorization: Bearer eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJhY2Nlc3Nfa2V5IjoibWVyY2hhbnRfYWNjZXNzX2tleSIsImlhdCI6MTYwMzcxMTQ3NSwiZXhwIjoxNjAzNzE1MDc1fQ.UYwRQXykcIVNzIjni3icf_FBbxSXZ_m-2SsFfz3zjBs ``` > Example request ```shell curl -X PATCH \ 'https://api.shipping.montonio.com/stores/store-webhook' \ -H 'Authorization: Bearer eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJhY2Nlc3Nfa2V5IjoiOTZlNjhlZDEtMDkzOC00NTE0LWFkZDEtYmE1MGE0NmI3YWZkIiwiaWF0IjoxNjAzNzE1MjczLCJleHAiOjE2MDM3MTg4NzN9.LpSPYEtkRd5Ze4RZoeN8rRs6hzNP1cqw_Th8x4oRCXo' -d '{ "tracking_webhook_url": "https://www.example.com/shipping-api-webhook" }' ``` URL `https://api.shipping.montonio.com/stores/store-webhook` Headers | Key | Required | Value | | ------------- | -------- | --------------------- | | Authorization | yes | `Bearer [your_token]` | Body | Key | Required | Data type | Notes | Example Value | | ---------------------- | -------- | --------- | --------------------------------------------------------------------------------------- | ------------------------------------------------ | | tracking\_webhook\_url | yes | `string` | The URL to send a webhook notification when a shipment is created or a label is printed | `"https://www.example.com/shipping-api-webhook"` | ## Receiving a webhook call If a webhook URL has been registered with the API, it will send a POST request with relevant data to the URL whenever a shipment is created or a label is printed for it. The data is stored in a `webhook_token` query parameter which needs to be decoded using your secret key. ### Validating the webhook token The `webhook_token` that is included in the webhook query parameter needs to be validated. The token is signed with your `Secret Key`. On the code panel you can see examples of validating the token. Show / Hide Parameters Headers | Key | Type | Description | | --- | -------- | --------------------- | | alg | `string` | Always set to `HS256` | | typ | `string` | Always set to `JWT` | Payload | Key | Type | Description | | ------------------- | -------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | | message | `string` | A short message indicating the event that triggered the hook (currently `shipment_created` or `label_created`) | | merchant\_reference | `string` | The order reference number you provided when creating the shipment | | shipment\_uuid | `string` | The shipment's UUID in Montonio. | | shipment\_status | `string` | Shipment status. `registered_with_provider` if shipment was created and successfully registered with the shipping provider. `label_created` when the label for the shipment has already been printed at least once. | | tracking\_numbers | `array` | An array containing one or more tracking code objects for the shipment (one for each parcel if multiparcel shipment), see below. | Payload: Tracking number | Key | Type | Description | | ---- | -------- | ---------------------------------------------------------------------------- | | code | `string` | The tracking code belonging to a parcel | | link | `string` | The full URL with the tracking code to the shipping provider's tracking page | Show / Hide Example Code ```javascript /** * We recommend using the jsonwebtoken package to verify * Json Web Tokens. You can install it with npm: * > npm install jsonwebtoken * More information can be found at * https://www.npmjs.com/package/jsonwebtoken */ const jwt = require('jsonwebtoken'); // fetched from the URL const webhook_token = 'eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJtZXNzYWdlIjoic2hpcG1lbnRfY3JlYXRlZCIsIm1lcmNoYW50X3JlZmVyZW5jZSI6Ijk1Iiwic2hpcG1lbnRfdXVpZCI6ImZkZGI2MWJhLTA4YTMtNDRkOS04NWJiLWIxYjExMjVmNzM4OSIsInNoaXBtZW50X3N0YXR1cyI6InJlZ2lzdGVyZWRfd2l0aF9wcm92aWRlciIsInRyYWNraW5nX251bWJlcnMiOlt7ImNvZGUiOiIwNTYwNTYwMDI4MTk3NSIsImxpbmsiOiJodHRwczovL3RyYWNraW5nLmRwZC5kZS9zdGF0dXMvZW4vcGFyY2VsLzA1NjA1NjAwMjgxOTc1In0seyJjb2RlIjoiMDU2MDU2MDAyODE5NzYiLCJsaW5rIjoiaHR0cHM6Ly90cmFja2luZy5kcGQuZGUvc3RhdHVzL2VuL3BhcmNlbC8wNTYwNTYwMDI4MTk3NiJ9XSwiaWF0IjoxNjUxNDk5NTU5LCJleHAiOjE2NTE1MTM5NTl9.8JIAn-1nyTcZf2SgNvCDtOELRBdLZdTOk5-kQNk8Ubs'; const decoded = jwt.verify(webhook_token, 'merchant_secret_key'); if (decoded.message === 'shipment_created') { // shipment created and registered with provider } else if (decoded.message === 'label_created') { // label printed for shipment } ``` ```php composer require firebase/php-jwt * More information can be found at * https://github.com/firebase/php-jwt */ use \Firebase\JWT\JWT; // fetched from the URL $webhook_token = 'eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJtZXNzYWdlIjoic2hpcG1lbnRfY3JlYXRlZCIsIm1lcmNoYW50X3JlZmVyZW5jZSI6Ijk1Iiwic2hpcG1lbnRfdXVpZCI6ImZkZGI2MWJhLTA4YTMtNDRkOS04NWJiLWIxYjExMjVmNzM4OSIsInNoaXBtZW50X3N0YXR1cyI6InJlZ2lzdGVyZWRfd2l0aF9wcm92aWRlciIsInRyYWNraW5nX251bWJlcnMiOlt7ImNvZGUiOiIwNTYwNTYwMDI4MTk3NSIsImxpbmsiOiJodHRwczovL3RyYWNraW5nLmRwZC5kZS9zdGF0dXMvZW4vcGFyY2VsLzA1NjA1NjAwMjgxOTc1In0seyJjb2RlIjoiMDU2MDU2MDAyODE5NzYiLCJsaW5rIjoiaHR0cHM6Ly90cmFja2luZy5kcGQuZGUvc3RhdHVzL2VuL3BhcmNlbC8wNTYwNTYwMDI4MTk3NiJ9XSwiaWF0IjoxNjUxNDk5NTU5LCJleHAiOjE2NTE1MTM5NTl9.8JIAn-1nyTcZf2SgNvCDtOELRBdLZdTOk5-kQNk8Ubs'; $decoded = Firebase\JWT\JWT::decode( $webhook_token, 'merchant_secret_key', array('HS256') ); if ($decoded->message === 'shipment_created') { // shipment created and registered with provider } else if ($decoded->message === 'label_created') { // label printed for shipment } ?> ``` ```python ''' We recommend using the PyJWT package to verify Json Web Tokens. You can install it with pip: > pip3 install PyJWT More information can be found at https://pyjwt.readthedocs.io/en/latest/ ''' import jwt # fetched from the URL webhook_token = 'eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJtZXNzYWdlIjoic2hpcG1lbnRfY3JlYXRlZCIsIm1lcmNoYW50X3JlZmVyZW5jZSI6Ijk1Iiwic2hpcG1lbnRfdXVpZCI6ImZkZGI2MWJhLTA4YTMtNDRkOS04NWJiLWIxYjExMjVmNzM4OSIsInNoaXBtZW50X3N0YXR1cyI6InJlZ2lzdGVyZWRfd2l0aF9wcm92aWRlciIsInRyYWNraW5nX251bWJlcnMiOlt7ImNvZGUiOiIwNTYwNTYwMDI4MTk3NSIsImxpbmsiOiJodHRwczovL3RyYWNraW5nLmRwZC5kZS9zdGF0dXMvZW4vcGFyY2VsLzA1NjA1NjAwMjgxOTc1In0seyJjb2RlIjoiMDU2MDU2MDAyODE5NzYiLCJsaW5rIjoiaHR0cHM6Ly90cmFja2luZy5kcGQuZGUvc3RhdHVzL2VuL3BhcmNlbC8wNTYwNTYwMDI4MTk3NiJ9XSwiaWF0IjoxNjUxNDk5NTU5LCJleHAiOjE2NTE1MTM5NTl9.8JIAn-1nyTcZf2SgNvCDtOELRBdLZdTOk5-kQNk8Ubs' try: decoded = jwt.decode( webhook_token, 'merchant_secret_key', algorithms=['HS256'] ) except jwt.exceptions.InvalidSignatureError as identifier: pass # Token validation failed if (decoded['message'] == 'shipment_created'): pass # shipment created and registered with provider elif (decoded['message'] == 'label_created'): pass # label printed for shipment ``` [Head back to Montonio](https://www.montonio.com) --- # Split URL: /api/split To start a Split application, a JWT (JSON Web Token) with payment instructions must be generated using your Secret Key. The customer will then be redirected to the Montonio Split client (financing.montonio.com) with this token as a query parameter. ## Generating the Payment Token :::note We recommend using popular community maintained libraries for JWT generation. You can browse the libraries for your programming language on the [jwt.io](https://jwt.io) website. ::: Show / Hide Parameters Payload | Key | Required | Type | Description | | ------------------------------------- | ----------- | --------- | ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | | loan\_type | yes | `string` | `split` | | access\_key | yes | `string` | Your Access Key for desired environment | | currency | yes | `string` | `EUR` | | merchant\_reference | yes | `string` | The order reference in the merchant system | | checkout\_products | yes | `array` | Array of products, see below | | checkout\_first\_name | yes\* | `string` | The customer's first name. Use this to identify customers more easily in Montonio's Partner System. | | checkout\_last\_name | yes\* | `string` | The customer's last name. Use this to identify customers more easily in Montonio's Partner System. | | checkout\_email | recommended | `string` | The customer's e-mail address | | checkout\_phone\_number | recommended | `string` | The customer's phone number | | checkout\_city | recommended | `string` | The city of the customer address | | checkout\_address | recommended | `string` | The address of the customer | | checkout\_postal\_code | recommended | `string` | The postal code (zip) of the customer | | preselected\_country | no | `string` | The preferred country for the application. Defaults to the merchant's country, if available. Available values are `EE` (others in development). | | preselected\_locale | recommended | `string` | `et` , `en_US` , `lt` | | preselected\_loan\_period | optional | `integer` | `1` , `2` , `3` | | merchant\_return\_url | recommended | `string` | The URL where the customer will be redirected back to after completing or cancelling a payment. [See below for details](#validating-the-financing-application) on financing application verification. | | merchant\_notification\_url | recommended | `string` | The URL to send a webhook notification to once a loan agreement has been signed. [See below for details](#webhook-notification) | | \*Required for Lithuanian stores only | | | | Payload: Products | Key | Required | Type | Description | | -------------- | -------- | ------------ | --------------------------------------- | | product\_name | yes | `string` | The product's name | | product\_price | yes | `float %.2f` | The product's sale price (tax included) | | quantity | yes | `integer` | Quantity of this product | :::caution Please make sure that the `product_price` is the price of the product for a quantity of 1. Montonio's API will multiply the individual product's price by the product's quantity on the server-side. ::: Show / Hide Code Examples ```javascript /** * We recommend using the jsonwebtoken package to generate * Json Web Tokens. You can install it with npm: * > npm install jsonwebtoken * More information can be found at * https://www.npmjs.com/package/jsonwebtoken */ const jwt = require('jsonwebtoken'); const payload = { "loan_type": "split", "access_key": "{{yourAccessKey}}", "currency": "EUR", "merchant_reference":"O036869", "checkout_first_name":"John", "checkout_last_name":"Smith", "checkout_email":"info@montonio.com", "checkout_phone":"5555555", "checkout_city":"Tallinn", "checkout_address":"Telliskivi 60a", "checkout_postal_code":"10412", "merchant_return_url": "https://mystore.com/montonio/payment/return?orderId=O036869" "merchant_notification_url": "https://mystore.com/montonio/payment/webhook?orderId=O036869", "preselected_locale": "et", "preselected_loan_period": 3 "checkout_products":[ { "product_name":"Shiny New Computer T490s", "product_price":1578.85, "quantity":2 }, { "product_name":"Standard delivery charges", "product_price":5, "quantity":1 } ], } const token = jwt.sign( payload, "{{yourSecretKey}}", { algorithm: "HS256", expiresIn: "10m" } ); console.log(token); ``` ```php 'split', 'access_key' => $accessKey, 'currency' => 'EUR', 'merchant_reference' => 'my-order-id-1', 'checkout_first_name' => 'Montonio', 'checkout_last_name' => 'Test', 'checkout_email' => 'test@montonio.com', 'checkout_phone_number' => '+37255555555', 'checkout_city' => 'Tallinn', 'checkout_address' => 'Customer Address', 'checkout_postal_code' => '11111', 'merchant_return_url' => 'https://my-store/return', // Where to redirect the checkout to after the payment 'merchant_notification_url' => 'https://my-store/notify', // We will send a webhook after the payment is complete, 'preselected_locale' => 'et' 'checkout_products' => array(), // For Montonio Split: // 'preselected_loan_period' => 3, ); // Add products $paymentData['checkout_products'][] = array( 'quantity' => (int) 1, 'product_name' => 'Some product name', 'product_price' => 35.52, ); /********************************************* * MONTONIO SPLIT * ******************************************/ // Make sure to add preselected_loan_period to Payment Data $paymentData['preselected_loan_period'] = 3; $montonioSplit = new MontonioSplitSDK( $accessKey, $secretKey, $env ); $montonioSplit->setPaymentData($paymentData); $splitPaymentUrl = $montonioSplit->getPaymentUrl(); echo $splitPaymentUrl; ``` ```php composer require firebase/php-jwt * More information can be found at * https://github.com/firebase/php-jwt */ use \Firebase\JWT\JWT; $payment_data = array( 'access_key' => 'merchant_access_key', // ... 'iat' => time(), 'exp' => time() + (60 * 10) ); $payment_token = \Firebase\JWT\JWT::encode($payment_data, 'merchant_secret_key', 'HS256'); echo $payment_token; // eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJhY2Nlc3Nfa2V5IjoibWVyY2hhbnRfYWNjZXNzX2tleSIsImlhdCI6MTYwMzcxMTQ3NSwiZXhwIjoxNjAzNzE1MDc1fQ.UYwRQXykcIVNzIjni3icf_FBbxSXZ_m-2SsFfz3zjBs ?> ``` ```python ''' We recommend using the PyJWT package to generate Json Web Tokens. You can install it with pip: > pip3 install PyJWT datetime More information can be found at https://pyjwt.readthedocs.io/en/latest/ ''' import jwt from datetime import datetime, timedelta, timezone payment_data = { 'access_key': 'merchant_access_key', # ... 'iat': datetime.now(timezone.utc), 'exp': datetime.now(timezone.utc) + timedelta(minutes=10) } payment_token = jwt.encode( payment_data, 'merchant_secret_key', algorithm='HS256' ).decode('utf-8') print(payment_token) # eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJhY2Nlc3Nfa2V5IjoibWVyY2hhbnRfYWNjZXNzX2tleSIsImlhdCI6MTYwMzcxMTQ3NSwiZXhwIjoxNjAzNzE1MDc1fQ.UYwRQXykcIVNzIjni3icf_FBbxSXZ_m-2SsFfz3zjBs ``` :::note The token's expiration time should be long enough to ensure that the customer arrives to Montonio's gateway in time but no longer than 10 minutes from the issuing time. Note that the expiration time will be validated only upon arrival to the gateway and that the customer can take longer than 10 minutes to complete the process. ::: ## Redirecting the Customer Once you have generated the payment token it's time to redirect the customer to Montonio's gateway. Append the `payment_token` to the gateway URL as a query parameter. Sandbox: [https://sandbox-financing.montonio.com](https://sandbox-financing.montonio.com) Production: [https://financing.montonio.com](https://financing.montonio.com) Example: ```console https://financing.montonio.com?payment_token=eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJhbW91bnQiOjEwLCJjdXJyZW5jeSI6IkVVUiIsImFjY2Vzc19rZXkiOiJtZXJjaGFudF9hY2Nlc3Nfa2V5IiwibWVyY2hhbnRfcmVmZXJlbmNlIjoiU082NjExMjMiLCJtZXJjaGFudF9yZXR1cm5fdXJsIjoiaHR0cHM6Ly9tb250b25pby5jb20vb3JkZXJzLzI3NzMxNzczL3RoYW5rX3lvdSIsIm1lcmNoYW50X25vdGlmaWNhdGlvbl91cmwiOiJodHRwczovL21vbnRvbmlvLmNvbS9vcmRlcnMvcGF5bWVudF93ZWJob29rIiwicGF5bWVudF9pbmZvcm1hdGlvbl91bnN0cnVjdHVyZWQiOiJQYXltZW50IGZvciBvcmRlciBTTzY2MTEyMyIsInByZXNlbGVjdGVkX2FzcHNwIjoiTEhWQkVFMjIiLCJwcmVzZWxlY3RlZF9sb2NhbGUiOiJldCIsImNoZWNrb3V0X2VtYWlsIjoidGVzdC1jdXN0b21lckBtb250b25pby5jb20iLCJpYXQiOjE2MDEwMjA4MjUsImV4cCI6MTYwMTAyMTQyNX0.RfRVHklL7irHGN309AYRTMOXnq6UWYT2Mxb42oMh4JY ``` ## Validating the Financing Application ### Redirect Back to the Merchant Once the customer completes the financing application, they will be redirected back to the `merchant_return_url` that you set in the original payment token with a new `payment_token` appended to the URL as a query parameter. Validate the contents and the signature of this token to confirm the order. [See below for details](#validating-the-returned-payment-token) on validating the token. Example return URL: ```console https://my-store.com/orders/27731773/thank_you?payment_token=eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJhbW91bnQiOjU3OC44NSwiY3VycmVuY3kiOiJFVVIiLCJhY2Nlc3Nfa2V5IjoiYzYxOWI1ZmQtOWYwNS00ZGY1LTlhNDEtYTIwODAzZDMzZGYwIiwibWVyY2hhbnRfcmVmZXJlbmNlIjoiU08wMzYtNDIyMiIsInN0YXR1cyI6ImZpbmFsaXplZCIsImFwcGxpY2F0aW9uX3V1aWQiOiJhZTRjYjIzZS1hZWRjLTQ4YzUtYmU0MC1iM2EwYTEzZjMzZmMiLCJwYXltZW50X21ldGhvZF9uYW1lIjoiU2xpY2UiLCJpYXQiOjE2MjI3Mjk0MjYsImV4cCI6MTYyMjc0MzgyNn0.ruT9q6dSQcV4y5dwPwov6Tr0s5FDuIks1Ayd8lxdBe4 ``` ### Webhook Notification Once you set the `merchant_notification_url` parameter in the original payment token, we will send a `POST` request to this URL with a new `payment_token` appended to it as a query parameter. Validate the contents and the signature of this token to confirm the order. [See below for details](#validating-the-returned-payment-token) on validating the token. ### Validating the Returned Payment Token The `payment_token` that is appended to the `merchant_return_url` when redirecting back to the merchant or to the `merchant_notification_url` when sending a webhook notification needs to be validated. The token is signed with your `Secret Key`. On the code panel you can see examples of validating the token. Show / Hide Parameters Headers | Key | Type | Description | | --- | -------- | --------------------- | | alg | `string` | Always set to `HS256` | | typ | `string` | Always set to `JWT` | Payload | Key | Type | Description | | --------------------- | -------- | ---------------------------------------------------------------------------------------- | | amount | `number` | Payment amount (up to 2 decimal places). | | currency | `string` | Currency used to placed the order (ISO 4217). | | access\_key | `string` | Your `Access Key` obtained from the Partner System. | | merchant\_reference | `string` | The order reference number you provided in the initial payment token. | | status | `string` | Payment status. Only consider `finalized` as the correct status for a completed payment. | | application\_uuid | `string` | The loan application ID in Montonio's system. | | payment\_method\_name | `string` | The friendly name of the payment method. | | exp | `number` | Expiration time of the token in Unix time. | | iat | `number` | Issuing time of the token in Unix time. | Show / Hide Code Examples ```javascript /** * We recommend using the jsonwebtoken package to verify * Json Web Tokens. You can install it with npm: * > npm install jsonwebtoken * More information can be found at * https://www.npmjs.com/package/jsonwebtoken */ const jwt = require('jsonwebtoken'); // fetched from the URL const payment_token = 'eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJhbW91bnQiOjU3OC44NSwiY3VycmVuY3kiOiJFVVIiLCJhY2Nlc3Nfa2V5IjoiYzYxOWI1ZmQtOWYwNS00ZGY1LTlhNDEtYTIwODAzZDMzZGYwIiwibWVyY2hhbnRfcmVmZXJlbmNlIjoiU08wMzYtNDIyMiIsInN0YXR1cyI6ImZpbmFsaXplZCIsImFwcGxpY2F0aW9uX3V1aWQiOiJhZTRjYjIzZS1hZWRjLTQ4YzUtYmU0MC1iM2EwYTEzZjMzZmMiLCJwYXltZW50X21ldGhvZF9uYW1lIjoiU2xpY2UiLCJpYXQiOjE2MjI3Mjk0MjYsImV4cCI6MTYyMjc0MzgyNn0.ruT9q6dSQcV4y5dwPwov6Tr0s5FDuIks1Ayd8lxdBe4'; // original order ID passed to merchant_reference const orderID = 'SO661123'; const decoded = jwt.verify(payment_token, 'merchant_secret_key'); if ( decoded.access_key === 'merchant_access_key' && decoded.merchant_reference === orderID && decoded.status === 'finalized' ) { // payment completed } else { // payment not completed } ``` ```php composer require firebase/php-jwt * More information can be found at * https://github.com/firebase/php-jwt */ use \Firebase\JWT\JWT; // fetched from the URL $payment_token = 'eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJhbW91bnQiOjU3OC44NSwiY3VycmVuY3kiOiJFVVIiLCJhY2Nlc3Nfa2V5IjoiYzYxOWI1ZmQtOWYwNS00ZGY1LTlhNDEtYTIwODAzZDMzZGYwIiwibWVyY2hhbnRfcmVmZXJlbmNlIjoiU08wMzYtNDIyMiIsInN0YXR1cyI6ImZpbmFsaXplZCIsImFwcGxpY2F0aW9uX3V1aWQiOiJhZTRjYjIzZS1hZWRjLTQ4YzUtYmU0MC1iM2EwYTEzZjMzZmMiLCJwYXltZW50X21ldGhvZF9uYW1lIjoiU2xpY2UiLCJpYXQiOjE2MjI3Mjk0MjYsImV4cCI6MTYyMjc0MzgyNn0.ruT9q6dSQcV4y5dwPwov6Tr0s5FDuIks1Ayd8lxdBe4'; // original order ID passed to merchant_reference $orderID = 'SO661123'; $decoded = Firebase\JWT\JWT::decode( $payment_token, 'merchant_secret_key', array('HS256') ); if ( $decoded->access_key === 'merchant_access_key' && $decoded->merchant_reference === $orderID && $decoded->status === 'finalized' ) { // payment completed } else { // payment not completed } ?> ``` ```python ''' We recommend using the PyJWT package to verify Json Web Tokens. You can install it with pip: > pip3 install PyJWT More information can be found at https://pyjwt.readthedocs.io/en/latest/ ''' import jwt # fetched from the URL payment_token = 'eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJhbW91bnQiOjU3OC44NSwiY3VycmVuY3kiOiJFVVIiLCJhY2Nlc3Nfa2V5IjoiYzYxOWI1ZmQtOWYwNS00ZGY1LTlhNDEtYTIwODAzZDMzZGYwIiwibWVyY2hhbnRfcmVmZXJlbmNlIjoiU08wMzYtNDIyMiIsInN0YXR1cyI6ImZpbmFsaXplZCIsImFwcGxpY2F0aW9uX3V1aWQiOiJhZTRjYjIzZS1hZWRjLTQ4YzUtYmU0MC1iM2EwYTEzZjMzZmMiLCJwYXltZW50X21ldGhvZF9uYW1lIjoiU2xpY2UiLCJpYXQiOjE2MjI3Mjk0MjYsImV4cCI6MTYyMjc0MzgyNn0.ruT9q6dSQcV4y5dwPwov6Tr0s5FDuIks1Ayd8lxdBe4' # original order ID passed to merchant_reference orderID = 'SO661123'; try: decoded = jwt.decode( payment_token, 'merchant_secret_key', algorithms=['HS256'] ) except jwt.exceptions.InvalidSignatureError as identifier: pass # Token validation failed if ( decoded['access_key'] == 'merchant_access_key' and decoded['merchant_reference'] == orderID and decoded['status'] == 'finalized' ): pass # payment completed else: pass # payment not completed ``` --- # PHP URL: /sdk/php --- # Connect Montonio flow for plugins URL: /api/plugins/plugin-connect-flow :::note This guide is for developers of e-commerce plugins and integrations (WooCommerce, PrestaShop, Magento, Shopify, custom platforms, etc.). It describes the **Connect Montonio** flow — an OAuth-style flow that provisions a merchant's API keys into your plugin automatically, replacing the manual copy/paste of Access Keys and Secret Keys. ::: ## Overview Traditionally, a merchant integrating Montonio has to open the [Partner System](https://partner.montonio.com), find their store's **Access Key** and **Secret Key** on the **API Keys** tab, and paste them into your plugin's settings by hand. This is error-prone and a common source of support tickets. The **Connect Montonio** flow removes the manual step. You add a single **Connect Montonio** button to your plugin's settings page. When the merchant clicks it, they are sent to the Partner System, they pick which store to connect and confirm, and their API keys are delivered back to your plugin automatically through a short-lived, one-time-code exchange. Conceptually this is an [OAuth 2.0](https://oauth.net/2/)-style authorization code flow: 1. **Your plugin** redirects the merchant to the Partner System with a `state` value and a `callbackUrl`. 2. **The merchant** logs in, selects a store, and consents. 3. **The Partner System** redirects the merchant's browser back to your `callbackUrl`, delivering a short-lived **one-time code**. 4. **Your plugin's backend** exchanges that one-time code for the store's API keys via a server-to-server call. 5. **Your plugin** stores the keys and is ready to make API requests. ```text ┌────────────┐ 1. redirect (state, callbackUrl) ┌──────────────────────┐ │ │ ───────────────────────────────────► │ │ │ │ │ Partner System │ │ Plugin │ 2. merchant consents │ partner.montonio.com │ │ │ │ │ │ │ ◄─────────────────────────────────── │ │ └────────────┘ 3. POST callback (code, state) └──────────────────────┘ │ │ 4. exchange one-time code (server-to-server) ┌──────────────────────┐ └──────────────────────────────────────────────► │ Montonio Connect │ │ activation endpoint │ ◄─────────────────────────────────────────────── │ │ 5. API keys returned └──────────────────────┘ ``` :::caution **Security note.** The `state` parameter is **required** throughout this flow and validating it on the callback is critical to prevent CSRF attacks. See [Step 3](#step-3-handle-the-callback). ::: ## Before you start - You need a **platform identifier** for your integration (for example `woocommerce`). Montonio assigns this to you — contact your Montonio integration partner to have your platform registered before going live. - Your plugin needs a **server-side callback endpoint** reachable over **HTTPS**. It receives a browser `POST` from the Partner System and must be able to make an outbound HTTPS request to Montonio. - Your plugin needs a place to persist a short-lived `state` value between the redirect and the callback (a session, a database row, or the platform's equivalent of an options store). ## Step 1: Send the merchant to the Partner System Render a **Connect Montonio** button in your plugin's settings. When the merchant clicks it: 1. **Generate a `state` value** — a cryptographically random string with at least 128 bits of entropy (16 random bytes, hex-encoded → 32 characters is a good baseline). 2. **Persist the `state`** server-side, associated with this merchant/session. You will compare against it when the callback arrives. 3. **Redirect the merchant's browser** to `https://partner.montonio.com/` with the query parameters below. ### Authorization request parameters | Parameter | Required | Description | | ------------- | -------- | --------------------------------------------------------------------------------------------------------- | | `action` | Yes | Must be the literal string `connect-plugin`. | | `platform` | Yes | Your assigned platform identifier, e.g. `woocommerce`. | | `storeUrl` | Yes | The merchant's store hostname, without protocol, e.g. `shop.example.com`. | | `callbackUrl` | Yes | The absolute **HTTPS** URL of your plugin's callback endpoint. The Partner System will `POST` back to it. | | `state` | Yes | The random anti-CSRF value you generated and persisted in step 2. | ### Example The resulting redirect looks like this: ```text https://partner.montonio.com/?action=connect-plugin&platform=woocommerce&storeUrl=shop.example.com&callbackUrl=https%3A%2F%2Fshop.example.com%2Fmontonio%2Fconnect-callback&state=9f8c1b7a2d3e4f5061728394a5b6c7d8 ``` Reference implementation (WooCommerce, PHP): ```php // 1. Generate and persist a random state value. $state = bin2hex( random_bytes( 16 ) ); update_option( 'montonio_connection_state', $state ); // 2. Build the callback URL your plugin exposes. $callback_url = 'https://shop.example.com/montonio/connect-callback'; // 3. Build the authorization URL and redirect the merchant. $query = http_build_query( [ 'action' => 'connect-plugin', 'platform' => 'woocommerce', 'storeUrl' => wp_parse_url( get_home_url(), PHP_URL_HOST ), 'callbackUrl' => $callback_url, 'state' => $state, ] ); $connect_url = 'https://partner.montonio.com/?' . $query; ``` ## Step 2: The merchant consents There is nothing to build for this step — it happens entirely in the Partner System. For reference, the merchant will: - Log in to their Montonio account (if not already logged in). - Select which **business** and **store** to connect. - Confirm that they authorize your plugin to use that store's API keys. If the store has no live (production) API keys yet, the Partner System informs the merchant that the connection will be made in **sandbox mode**. The merchant can also cancel — see how to handle that in Step 3. Once the merchant confirms, the Partner System redirects the browser back to your `callbackUrl` with a browser-initiated `POST`. ## Step 3: Handle the callback Your `callbackUrl` receives an HTTP **`POST`** with a form-encoded body containing the following fields: | Field | Description | | ---------------- | ----------------------------------------------------------------------- | | `connectionUuid` | A UUID (v4) identifying this connection attempt. | | `oneTimeCode` | The short-lived code you exchange for API keys in Step 4. | | `state` | The same `state` value you sent in Step 1, echoed back. | | `cancelled` | The string `true` if the merchant cancelled; otherwise empty or absent. | Your callback handler **must** perform the following checks, in order, before doing anything else: ### 1. Require POST Reject the request if it is not a `POST`. ### 2. Validate the `state` — this prevents CSRF :::caution **Do not skip this.** The `state` check is what ties the callback back to the redirect *your plugin* initiated. Without it, an attacker could forge a callback request to a logged-in merchant's admin and trick your plugin into activating a connection — and therefore installing API keys — that the merchant never authorized. This is a classic CSRF (cross-site request forgery) attack. ::: Load the `state` you persisted in Step 1 and compare it against the `state` from the callback body: - The received `state` must be **non-empty**. - It must **match** the stored value. - Use a **constant-time** string comparison (e.g. `hash_equals` in PHP, `crypto.timingSafeEqual` in Node.js) to avoid timing attacks. - **Consume the `state` immediately** after a successful comparison (delete it), so it cannot be replayed. If the `state` is missing or does not match, **abort** the flow and show an error. Do not proceed to the exchange. ### 3. Handle cancellation If `cancelled` is `true`, the merchant declined. Stop and show a neutral "connection cancelled" message. ### 4. Validate the payload Ensure `connectionUuid` and `oneTimeCode` are present, and that `connectionUuid` is a well-formed UUID v4. Reject malformed input. ### Example ```php // Runs when the Partner System POSTs to your callback URL. if ( strtoupper( $_SERVER['REQUEST_METHOD'] ) !== 'POST' ) { // Reject non-POST requests. exit; } $connection_uuid = sanitize_text_field( $_POST['connectionUuid'] ?? '' ); $one_time_code = sanitize_text_field( $_POST['oneTimeCode'] ?? '' ); $state = sanitize_text_field( $_POST['state'] ?? '' ); $cancelled = sanitize_text_field( $_POST['cancelled'] ?? '' ); // Validate state (CSRF protection) using a constant-time comparison. $stored_state = (string) get_option( 'montonio_connection_state', '' ); if ( '' === $state || ! hash_equals( $stored_state, $state ) ) { delete_option( 'montonio_connection_state' ); // Abort: state mismatch, possible CSRF attempt. exit; } delete_option( 'montonio_connection_state' ); // single-use if ( 'true' === $cancelled ) { // Merchant cancelled — show a neutral message. exit; } if ( empty( $connection_uuid ) || empty( $one_time_code ) ) { // Missing required fields. exit; } ``` ## Step 4: Exchange the one-time code for API keys From your plugin's **backend** (never the browser), make a server-to-server `POST` to the Montonio Connect activation endpoint: **`POST https://plugin-telemetry.montonio.com/api/connections/activate`** Request headers: ```text Content-Type: application/json Accept: application/json ``` Request body: ```json { "connectionUuid": "660e8400-e29b-41d4-a716-446655440111", "oneTimeCode": "Drmhze6EPcv0fN_81Bj-nA_rZvUlUjPjRKLQMEe4ydY", "state": "9f8c1b7a2d3e4f5061728394a5b6c7d8" } ``` | Field | Required | Description | | ---------------- | -------- | ---------------------------------------------------------- | | `connectionUuid` | Yes | The `connectionUuid` from the callback. | | `oneTimeCode` | Yes | The `oneTimeCode` from the callback. | | `state` | Yes | The same `state` value; it is validated again server-side. | ### Successful response On success you receive `200 OK` with the store's details and API keys: ```json { "connectionUuid": "660e8400-e29b-41d4-a716-446655440111", "storeUuid": "550e8400-e29b-41d4-a716-446655440000", "storeName": "Example Store", "storeUrl": "shop.example.com", "businessLegalName": "Example LLC", "liveKeysAvailable": true, "productionApiKey": { "accessKey": "...", "secretKey": "..." }, "sandboxApiKey": { "accessKey": "...", "secretKey": "..." } } ``` | Field | Description | | --------------------------------------------------------- | ------------------------------------------------------------------------------------- | | `liveKeysAvailable` | `true` if the store has production keys. If `false`, only connect in sandbox mode. | | `productionApiKey` | The live Access Key / Secret Key pair, or `null` when `liveKeysAvailable` is `false`. | | `sandboxApiKey` | The sandbox Access Key / Secret Key pair, or `null` if no sandbox key exists. | | `storeName`, `businessLegalName`, `storeUrl`, `storeUuid` | Store metadata you can display or store for reference. | ### The one-time code is short-lived and single-use :::caution The one-time code expires **5 minutes** after it is issued and can be exchanged **only once**. Perform the exchange from your callback handler immediately. ::: If the code is invalid, expired, already used, or the `state` does not match, the endpoint responds with **`410 Gone`** and an `INVALID_OR_EXPIRED_CODE` error. Treat any non-`200` response as a failed activation, surface a clear error to the merchant, and let them retry the **Connect Montonio** button (which starts a fresh flow with a new `state`). ### Example ```php $response = wp_remote_post( 'https://plugin-telemetry.montonio.com/api/connections/activate', [ 'timeout' => 15, 'headers' => [ 'Content-Type' => 'application/json', 'Accept' => 'application/json', ], 'body' => wp_json_encode( [ 'connectionUuid' => $connection_uuid, 'oneTimeCode' => $one_time_code, 'state' => $state, ] ), ] ); $code = wp_remote_retrieve_response_code( $response ); if ( 200 !== (int) $code ) { // Activation failed (e.g. 410 INVALID_OR_EXPIRED_CODE). Show an error and let the merchant retry. exit; } $body = json_decode( wp_remote_retrieve_body( $response ), true ); ``` ## Step 5: Store the keys and finish Persist the returned credentials in your plugin's settings and mark the store as connected: - If `liveKeysAvailable` is `true`, save `productionApiKey.accessKey` / `productionApiKey.secretKey` and switch the plugin to live mode. - Save `sandboxApiKey.accessKey` / `sandboxApiKey.secretKey` for testing. If `liveKeysAvailable` is `false`, connect in **sandbox mode** only. - Store the `connectionUuid` alongside the keys — it identifies this connection for future reference. :::caution **Treat the activation response as a secret.** The Access Keys and Secret Keys it returns are sensitive credentials that authenticate as the merchant's store. As soon as you receive the response: - Write the keys **only** to your secure persistence layer — never to application logs, error trackers, request/response dumps, analytics, or the browser. - Make sure the raw response body is not logged anywhere by default (many HTTP clients log full responses when in debug mode — disable that for this call). - Never send the Secret Key to the frontend or embed it in any client-side code. ::: After saving, you can immediately use the keys to call Montonio's APIs — for example, fetch and cache the store's available payment methods (see [Display payment methods](/api/stargate/guides/payment-methods)). Finally, redirect the merchant back to your settings page with a success message. ## Reconnecting and disconnecting - **Reconnecting.** Running the flow again simply issues a fresh set of credentials and overwrites the stored keys. Always generate a **new `state`** for every attempt. - **Disconnecting.** Provide a **Disconnect** action in your settings that clears the stored keys (`accessKey`, `secretKey`, sandbox keys, and `connectionUuid`) and returns the plugin to its unconnected state. Protect this action against CSRF too (e.g. a nonce and a capability/permission check for admin users). ## Security checklist - ✅ Generate a fresh, cryptographically random `state` (≥ 128 bits) for every connection attempt. - ✅ Persist the `state` server-side and **validate it on the callback with a constant-time comparison** — this is your primary CSRF defense. - ✅ Consume the `state` after a single use so callbacks cannot be replayed. - ✅ Accept the callback only over `POST`, and restrict it to authenticated admin users where your platform allows. - ✅ Perform the code-for-keys exchange **server-to-server**, never from the browser. - ✅ Serve your `callbackUrl` over HTTPS. - ✅ Store API keys securely, and **never log them** or the raw activation response (logs, error trackers, analytics) — never expose the Secret Key to the browser. ## Reference implementation The Montonio **WooCommerce** plugin implements this flow end to end and is a good reference. The PHP snippets in this guide mirror that implementation. If you are building for another platform, replicate the same contract: the redirect parameters in Step 1, the callback handling and `state` validation in Step 3, and the activation exchange in Step 4. --- # Shipping URL: /api/shipping-v2 --- # Shipping URL: /api/shipping-v2/overview The Montonio Shipping API allows you to create and manage shipments with multiple carriers. This guide focuses on fetching and displaying shipping methods, registering shipments, and creating shipping labels. The [Guides](/api/shipping-v2/guides) section contains detailed instructions and code examples on integrating with the API. :::note Before starting the integration, we recommend you familiarize yourself with the basic concepts of the API, which are described below. ::: ## General flow to complete the integration 1. Create a [Webhook](/api/shipping-v2/guides/webhooks) to receive notifications 2. Retrieve available [Shipping Methods](/api/shipping-v2/guides/shipping-methods) for your store 3. Create a [Shipment](/api/shipping-v2/guides/shipments) 4. Create a [Label File](/api/shipping-v2/guides/labels) ## What is a Shipment? A shipment can be viewed as a container containing the essential information about parcels that need to be delivered from point A to point B. Before creating a shipment, you must retrieve your store's available [shipping methods](/api/shipping-v2/guides/shipping-methods). This will provide you with a list of options for transporting the parcels. To create a [shipment](/api/shipping-v2/guides/shipments), you must specify details such as sender and receiver information, a shipping method, and the parcels included in the Shipment. A shipment can contain one or more parcels. Once the Shipment is registered with the Carrier, you can create a [label file](/api/shipping-v2/guides/labels) for it. A label file can contain one or more shipping labels, which should be attached to the parcel. ## What shipping methods can be used? A Shipment can be delivered using one of the available methods, which should be specified when creating the Shipment. They are: | Shipping method type | Examples | | -------------------- | ---------------------------------------------- | | **Courier** | `Standard courier` | | **Pickup point** | `Parcel machine`, `parcel shop`, `post office` | ## What is the lifecycle of a Shipment? By default, our API uses **asynchronous processing** to register shipments with carriers. This is the recommended approach as it provides robust handling of carrier API issues. For simpler integrations, you can opt for **synchronous processing** by setting `synchronous: true` - see the [Shipments guide](/api/shipping-v2/guides/shipments#synchronous-vs-asynchronous-flow) for details. When using asynchronous processing, you must create a [webhook](/api/shipping-v2/guides/webhooks) to listen for shipment lifecycle events. We use the `status` property to communicate a shipment's status. You will receive a webhook notification via an HTTP POST request whenever a shipment transitions from one status to another. You can expect the following values for `status`: | Status | Description | | ---------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------- | | **pending** | The Shipment has been created but is not yet registered with the Carrier. Shipment will be registered asynchronously. Label file cannot be created yet. | | **registered** | Shipment has been registered with the Carrier. Label file creation is now possible. | | **registrationFailed** | We could not register the shipment previously in status pending. | | **labelsCreated** | A label file is successfully created for the Shipment. | | **inTransit** | The Carrier picked up the Shipment from the sender. This means one or more parcels have been picked up and will be delivered to the receiver. | | **awaitingCollection** | One or more parcels are ready to be picked up from the pickup point. This is only used for pickup point shipments. | | **delivered** | All parcels are delivered to the receiver. | | **returned** | One or more parcels are returned to the sender. | ## What is the lifecycle of a Label File? By default, we use **asynchronous processing** to create the [label file](/api/shipping-v2/guides/labels). For simpler integrations, you can opt for **synchronous processing** by setting `synchronous: true` - see the [Labels guide](/api/shipping-v2/guides/labels#synchronous-vs-asynchronous-flow) for details. When using asynchronous processing, ensure you include the correct event type when creating a webhook. A label file is a PDF that contains one or more shipping labels. To communicate the status of the label file generation process, we use the `status` property. Whenever a label file transitions from one status to another, you will receive a webhook notification via an HTTP POST request. You can expect the following values for `status`: | Status | Description | | ----------- | ------------------------------------------------------------------------------------------------------------------------ | | **pending** | The Label File entity is created, but the PDF file is not ready for download. The file creation process is asynchronous. | | **ready** | The Label File is successfully generated and can now be downloaded. | | **failed** | Label File generation failed. Under normal circumstances, this should not happen. | ## How to access the API? > The API Base URLs for the available environments are as follows: > > - **Production**: `https://shipping.montonio.com/api/v2` > - **Sandbox**: `https://sandbox-shipping.montonio.com/api/v2` Read more about the sandbox environment [here](/api/shipping-v2/guides/sandbox). To authenticate with the API, you'll need to use API keys. Read more about [API keys](/introduction#api-keys) and how to get them. The authentication mechanism is described in the [Authentication section](/api/shipping-v2/reference#authentication) of the API reference. ## Getting started To build your integration step-by-step, dive deeper into the [Developer guides](/api/shipping-v2/guides). We also have a Swagger API reference, which you can find [here](https://shipping.montonio.com/docs). Happy coding! 🚀 --- # Shipping URL: /api/shipping-v2/reference Welcome to the Montonio Shipping API developer documentation. Here, you can find instructions on how to integrate with Montonio Shipping. ## API URLs API Base URLs for the available environments are as follows: > - **Production**: `https://shipping.montonio.com/api/v2` > - **Sandbox**: `https://sandbox-shipping.montonio.com/api/v2` Read more about the sandbox environment in the [Sandbox guide](/api/shipping-v2/guides/sandbox). ## Authentication The Shipping API uses [JWT (JSON Web Tokens)](https://jwt.io/) for authentication. All the endpoints require a JWT in the Authorization header as a Bearer token. JWT must contain your `Access Key` and be signed with your `Secret` Key using HMAC SHA256 (HS256). Read more about [API keys here](/introduction#api-keys). The exact implementation of generating the JWT varies by programming language, and you can see some examples on the code panel. We recommend using popular community-maintained libraries for generating and verifying JWTs. Visit [jwt.io](https://jwt.io/) to learn more about JWTs, find libraries for your programming language, or debug and verify your JWTs. ### JWT headers | Key | Required | Type | Description | | --- | -------- | -------- | ---------------------- | | alg | yes | `string` | Must be set to `HS256` | | typ | yes | `string` | Must be set to `JWT` | ### JWT payload Here is the minimum required payload for all requests: | Key | Required | Type | Description | | --------- | -------- | -------- | ------------------------------------------------------------------------------------------------------ | | accessKey | yes | `string` | Your `Access Key` obtained from the Partner System. | | exp | yes | `number` | Expiration time of the token in Unix time. We recommend setting this to 1 hour from issuing the token. | ```javascript /** * We recommend using the jsonwebtoken package to generate * Json Web Tokens. You can install it with npm: * > npm install jsonwebtoken * More information can be found at * https://www.npmjs.com/package/jsonwebtoken */ import jwt from 'jsonwebtoken'; const payload = { accessKey: 'MY_ACCESS_KEY' }; const authHeader = jwt.sign( payload, 'MY_SECRET_KEY', { algorithm: 'HS256', expiresIn: '1h' } ); console.log(authHeader); // eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJhY2Nlc3NLZXkiOiJNWV9BQ0NFU1NfS0VZIiwiaWF0IjoxNjc1OTM4NjM3LCJleHAiOjE2NzU5NDIyMzd9.f-wXP8t5HGhr5XKAl3eCeWbHnY3SO9DcY5WiWo06-uQ ``` ```php composer require firebase/php-jwt * More information can be found at * https://github.com/firebase/php-jwt */ // Should be loaded only once in the app, check composer docs for the specific framework you are using require __DIR__ . '/vendor/autoload.php'; use \Firebase\JWT\JWT; $payload = [ 'accessKey' => 'MY_ACCESS_KEY', 'iat' => time(), 'exp' => time() + (60 * 60) ]; $token = JWT::encode($payload, 'MY_SECRET_KEY', 'HS256'); // var_dump($token); // eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.eyJhY2Nlc3NLZXkiOiJNWV9BQ0NFU1NfS0VZIiwiaWF0IjoxNjc2MDQ1NTg5LCJleHAiOjE2NzYwNDkxODl9.9kz7LBZZVJrJbSO_42NTTg1Wg4HEP01cqOw0IzQ0nXU ``` ```python ''' We recommend using the PyJWT package to generate Json Web Tokens. You can install it with pip: > pip3 install PyJWT datetime More information can be found at https://pyjwt.readthedocs.io/en/latest/ ''' import jwt from datetime import datetime, timedelta, timezone payload = { 'accessKey': 'MY_ACCESS_KEY', 'iat': datetime.now(timezone.utc), 'exp': datetime.now(timezone.utc) + timedelta(hours=1) } auth_header = jwt.encode( payload, 'MY_SECRET_KEY', algorithm='HS256' ) print(auth_header) # eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJhY2Nlc3Nfa2V5IjoibWVyY2hhbnRfYWNjZXNzX2tleSIsImlhdCI6MTYwMzcxMTQ3NSwiZXhwIjoxNjAzNzE1MDc1fQ.UYwRQXykcIVNzIjni3icf_FBbxSXZ_m-2SsFfz3zjBs ``` ## Common API response codes Some response codes apply to all the endpoints listed below. | Http code | Description | | --------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ | | `400` | Input data validations failed. There might be some validation issues with the request body, query params, or URL parameters. Please review the request body requirements to fix the issue. | | `401` | `JWT` token validation failed. Please check the authentication guide to construct a valid token. | | `404` | Requested or related resource is not found. The entity that you are trying to retrieve does not exist. | ## API endpoints ### Get all carriers The endpoint allows you to fetch all carriers available through the Montonio Shipping API. It will tell you which carriers can be activated, which are already activated, and whether the carrier supports a Montonio contract. #### Endpoint path ```http GET /carriers ``` #### Authentication Refer to the [Authentication section](/api/shipping-v2/reference#authentication). Follow instructions for GET endpoints. #### Headers | Key | Required | Value | | ------------- | -------- | --------------------- | | Authorization | yes | `Bearer [your_token]` | #### Example request ```shell curl -X 'GET' \ 'https://shipping.montonio.com/api/v2/carriers' \ -H 'accept: application/json' \ -H 'Authorization: Bearer [your_token]' ``` Show / Hide Response Data ```json { "carriers": [ { "id": "aa8c5e19-ab56-425a-b8b8-7564b690a080", "code": "smartpost", "name": "SmartPosti", "logoUrl": "https://public.montonio.com/images/carrier_logos/smartpost.svg", "contracts": null, "hasMontonioContract": true, "supportedContractTypes": ["DIRECT", "MONTONIO"] }, { "id": "d292aff8-709e-4d46-9e49-be0a9670eddf", "code": "omniva", "name": "Omniva", "logoUrl": "https://public.montonio.com/images/carrier_logos/omniva.svg", "contracts": [ { "id": "8c804942-4258-4fb1-b1a3-e3ac391f303c", "carrierId": "d292aff8-709e-4d46-9e49-be0a9670eddf", "country": "EE", "lastUsedParcelNumber": null, "daysAllowedForReturns": null, "isDirectContract": true, "createdAt": "2024-05-28T08:00:40.404Z", "returnsAllowed": false, "parcelHandoverMethod": null, "defaultLockerSize": null, "logisticsContractNumber": null, "credentials": { "username": "my_username" } } ], "hasMontonioContract": true, "supportedContractTypes": ["DIRECT", "MONTONIO"] }, { "id": "cc118dac-f9e0-4163-b281-7006fddc08e7", "code": "dpd", "name": "DPD", "logoUrl": "https://public.montonio.com/images/carrier_logos/dpd.svg", "contracts": [ { "id": "b75774ef-e5d0-451b-81be-bf346ed959b1", "carrierId": "cc118dac-f9e0-4163-b281-7006fddc08e7", "country": "EE", "lastUsedParcelNumber": null, "daysAllowedForReturns": null, "isDirectContract": true, "createdAt": "2024-05-29T08:05:23.295Z", "returnsAllowed": false, "parcelHandoverMethod": null, "defaultLockerSize": null, "logisticsContractNumber": null, "credentials": { "username": "my_username" } } ], "hasMontonioContract": true, "supportedContractTypes": ["DIRECT", "MONTONIO"] }, { "id": "8c6fa25b-3ee9-46e1-afd6-570d6b4ec1fe", "code": "venipak", "name": "Venipak", "logoUrl": "https://public.montonio.com/images/carrier_logos/venipak.svg", "contracts": [ { "id": "a74349d7-d1d8-46a8-87d6-c750a6a1343b", "carrierId": "8c6fa25b-3ee9-46e1-afd6-570d6b4ec1fe", "country": "EE", "lastUsedParcelNumber": 12350, "daysAllowedForReturns": null, "isDirectContract": true, "createdAt": "2024-05-28T10:07:34.086Z", "returnsAllowed": false, "parcelHandoverMethod": null, "defaultLockerSize": null, "logisticsContractNumber": null, "credentials": { "username": "my_username" } } ], "hasMontonioContract": false, "supportedContractTypes": ["DIRECT"] } ] } ``` #### Response codes | Http code | Description | | --------- | ------------------------------------------------------------------------------------------ | | `200` | Represents the request has been processed successfully. It will return all store carriers. | #### Response fields | Key | Type | Description | | ------------------------------------------------ | ------------------ | ----------------------------------------------------------------------------------- | | `carriers` | `array` | List of carriers available through Montonio Shipping. | | `carriers[].id` | `string` | Unique identifier of the carrier. | | `carriers[].code` | `string` | Carrier code used in API requests. | | `carriers[].name` | `string` | Display name of the carrier. | | `carriers[].logoUrl` | `string` | URL to the carrier's logo image. | | `carriers[].contracts` | `array` or `null` | List of active contracts for this carrier, or `null` if no contracts are activated. | | `carriers[].hasMontonioContract` | `boolean` | Whether this carrier supports Montonio contracts (required for rate calculation). | | `carriers[].supportedContractTypes` | `array` | List of contract types the carrier supports: `DIRECT`, `MONTONIO`, or both. | | `carriers[].contracts[].id` | `string` | Unique identifier of the contract. | | `carriers[].contracts[].carrierId` | `string` | Reference to the carrier. | | `carriers[].contracts[].country` | `string` | Country code for the contract (ISO 3166-2). | | `carriers[].contracts[].lastUsedParcelNumber` | `number` or `null` | Last used parcel number for sequential numbering. | | `carriers[].contracts[].daysAllowedForReturns` | `number` or `null` | Number of days allowed for returns. | | `carriers[].contracts[].isDirectContract` | `boolean` | Whether this is a direct contract with the carrier. | | `carriers[].contracts[].returnsAllowed` | `boolean` | Whether returns are enabled for this contract. | | `carriers[].contracts[].parcelHandoverMethod` | `string` or `null` | Parcel handover method (Unisend only): `COURIER`, `LOCKER`, or `null`. | | `carriers[].contracts[].defaultLockerSize` | `string` or `null` | Default locker size (Unisend only): `S`, `M`, `L`, `XL`, or `null`. | | `carriers[].contracts[].logisticsContractNumber` | `string` or `null` | Logistics contract number if applicable. | | `carriers[].contracts[].credentials` | `object` | Contract credentials information. | | `carriers[].contracts[].credentials.username` | `string` or `null` | Username for direct contracts (masked for security). | | `carriers[].contracts[].createdAt` | `string` | ISO 8601 timestamp of when the contract was created. | ### Get shipping methods for a store The endpoint lets you fetch available carriers with shipping methods grouped by country for your store. This enables you to display the available carriers and their shipping methods by country. #### Endpoint path ```http GET /shipping-methods ``` #### Authentication Refer to the [Authentication section](/api/shipping-v2/reference#authentication). Follow instructions for GET endpoints. #### Headers | Key | Required | Value | | ------------- | -------- | --------------------- | | Authorization | yes | `Bearer [your_token]` | #### Example request ```shell curl -X 'GET' \ 'https://shipping.montonio.com/api/v2/shipping-methods' \ -H 'accept: application/json' \ -H 'Authorization: Bearer [your_token]' ``` Show / Hide Response Data ```json { "countries": [ { "carriers": [ { "carrierCode": "dpd", "shippingMethods": [ { "type": "courier", "subtypes": [ { "code": "standard" } ], "constraints": { "parcelDimensionsRequired": false } }, { "type": "pickupPoint", "subtypes": [ { "code": "parcelMachine" }, { "code": "parcelShop" } ], "constraints": { "parcelDimensionsRequired": false } } ] }, { "carrierCode": "omniva", "shippingMethods": [ { "type": "courier", "subtypes": [ { "code": "standard" } ], "constraints": { "parcelDimensionsRequired": false } }, { "type": "pickupPoint", "subtypes": [ { "code": "parcelMachine" }, { "code": "postOffice" } ], "constraints": { "parcelDimensionsRequired": false } } ] } ], "countryCode": "EE" } ] } ``` #### Response codes | Http code | Description | | --------- | -------------------------------------------------------------------------------------------------- | | `200` | Represents the request has been processed successfully. It will return all store shipping methods. | #### Response fields Each shipping method in the response includes: | Key | Type | Description | | -------------------------------------- | --------- | ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | | `type` | `string` | The type of shipping method. Available values: `courier`, `pickupPoint`. | | `subtypes` | `array` | List of subtypes available for this shipping method. | | `subtypes[].code` | `string` | Subtype identifier. For `pickupPoint`: `parcelMachine`, `postOffice`, `parcelShop`. For `courier`: `standard`, `standardB2B`. | | `constraints` | `object` | Constraints and requirements for this shipping method. | | `constraints.parcelDimensionsRequired` | `boolean` | Whether parcel dimensions (length, width, height) are required when creating shipments with this shipping method. When `true`, the `length`, `width`, and `height` fields must be provided for each parcel in the shipment request. | :::note The `parcelDimensionsRequired` flag varies by carrier, shipping method, and country. Always check the flag in the API response for accurate requirements when displaying shipping options and conditionally require dimension inputs in the checkout flow when the flag is `true`. ::: ### Get pickup points for a store The endpoint allows you to fetch carrier-specific pickup points for your store. If you use the `type` query param, you can further narrow down your search results. :::note The types of pickup points vary depending on the country and carrier. To find out all the possible options for a carrier and country, fetch the pickup points without the type query parameter and group the results by "type". ::: #### Endpoint path ```http GET /shipping-methods/pickup-points ``` #### Authentication Refer to the [Authentication section](/api/shipping-v2/reference#authentication). Follow instructions for GET endpoints. #### Headers | Key | Required | Value | | ------------- | -------- | --------------------- | | Authorization | yes | `Bearer [your_token]` | #### Query Params | Key | Type | Required | Value | | ------------- | ------ | -------- | ------------------------------------------------------------------------------------------------------------------------ | | `carrierCode` | string | yes | Use /carriers or /shipping-methods endpoint to get the list of carriers and the corresponding code for each. | | `countryCode` | string | yes | Receiver country code. Country codes are defined by the [ISO 3166-2](https://en.wikipedia.org/wiki/ISO_3166-2) standard. | | `type` | string | no | Available values: `postOffice`,`parcelShop`,`parcelMachine` | #### Example request ```shell curl -X 'GET' \ 'https://shipping.montonio.com/api/v2/shipping-methods/pickup-points?carrierCode=omniva&countryCode=EE&type=parcelMachine' \ -H 'accept: application/json' \ -H 'Authorization: Bearer [your_token]' ``` Show / Hide Response Data ```json { "pickupPoints": [ { "id": "98b391d7-5299-447c-9ad7-6b4042ef8b2f", "name": "Laagri Coop Maksimarketi pakiautomaat", "type": "parcelMachine", "streetAddress": "Pärnu mnt 558a", "locality": "Laagri alevik", "postalCode": "96067", "carrierCode": "omniva", "additionalServices": [ { "code": "cod" }, { "code": "ageVerification" } ] }, { "id": "0739f3d5-a500-4f15-8432-a03ed6f82e91", "name": "Laagri Veskitammi Maxima X pakiautomaat", "type": "parcelMachine", "streetAddress": "Veskitammi tn 3", "locality": "Laagri alevik", "postalCode": "96381", "carrierCode": "omniva", "additionalServices": [] } ], "countryCode": "EE" } ``` #### Response codes | Http code | Description | | --------- | ------------------------------------------- | | `200` | Return all the pickup points for the store. | #### Response fields Each pickup point in the response includes: | Key | Type | Description | | -------------------- | -------- | -------------------------------------------------------------------------------------------------------------------------- | | `id` | `string` | The unique identifier of the pickup point. Use this as the `shippingMethod.id` when creating a shipment. | | `name` | `string` | The name of the pickup point. | | `type` | `string` | The type of pickup point. Values: `parcelMachine`, `postOffice`, `parcelShop`. | | `streetAddress` | `string` | The street address of the pickup point. | | `locality` | `string` | The city or locality of the pickup point. | | `postalCode` | `string` | The postal code of the pickup point. | | `carrierCode` | `string` | The carrier code for this pickup point. | | `additionalServices` | `array` | List of additional services available for this pickup point. Each service has a `code` field (`cod` or `ageVerification`). | :::note The `additionalServices` array indicates which additional services can be used when creating a shipment to this pickup point. Only include services in your shipment request that are listed here. ::: ### Get courier services for a store The endpoint allows you to **fetch carrier-specific courier services for your store**. #### Endpoint path ```http GET /shipping-methods/courier-services ``` #### Authentication Refer to the [Authentication section](/api/shipping-v2/reference#authentication). Follow instructions for GET endpoints. #### Headers | Key | Required | Value | | ------------- | -------- | --------------------- | | Authorization | yes | `Bearer [your_token]` | #### Query Params | Key | Type | Required | Value | | ------------- | ------ | -------- | ------------------------------------------------------------------------------------------------------------------------ | | `carrierCode` | string | yes | Use the `/carriers` or `/shipping-methods` endpoint to get available carrier codes. | | `countryCode` | string | yes | Receiver country code. Country codes are defined by the [ISO 3166-2](https://en.wikipedia.org/wiki/ISO_3166-2) standard. | #### Example request ```shell curl -X 'GET' \ 'https://shipping.montonio.com/api/v2/shipping-methods/courier-services?carrierCode=omniva&countryCode=EE' \ -H 'accept: application/json' \ -H 'Authorization: Bearer [your_token]' ``` Show / Hide Response Data ```json { "courierServices": [ { "id": "0ffb9b04-3927-462a-a393-4f1e21f2ee55", "name": "Standard", "type": "standard", "carrierCode": "omniva", "additionalServices": [ { "code": "cod" } ] } ], "countryCode": "EE" } ``` #### Response codes | Http code | Description | | --------- | ---------------------------------------------- | | `200` | Return all the courier services for the store. | #### Response fields Each courier service in the response includes: | Key | Type | Description | | -------------------- | -------- | ----------------------------------------------------------------------------------------------------------------------------- | | `id` | `string` | The unique identifier of the courier service. Use this as the `shippingMethod.id` when creating a shipment. | | `name` | `string` | The display name of the courier service. | | `type` | `string` | The type of courier service. Values: `standard`, `standardB2B`. | | `carrierCode` | `string` | The carrier code for this courier service. | | `additionalServices` | `array` | List of additional services available for this courier service. Each service has a `code` field (`cod` or `ageVerification`). | :::note The `additionalServices` array indicates which additional services can be used when creating a shipment with this courier service. Only include services in your shipment request that are listed here. ::: ### Get possible shipping methods for given parcels The endpoint allows you to **fetch all shipping methods considering the parcel dimensions**. This is a way to validate which shipping methods are available for a specific route, considering parcels and dimensions. For example, parcel machines have specific weight and dimension limits. #### Endpoint path ```http POST /shipping-methods/filter-by-parcels ``` #### Authentication Refer to the [Authentication section](/api/shipping-v2/reference#authentication). Follow instructions for GET endpoints. #### Headers | Key | Required | Value | | ------------- | -------- | --------------------- | | Authorization | yes | `Bearer [your_token]` | #### Query Params | Key | Type | Required | Value | | ------------- | ------ | -------- | --------------------------------------------------------------------------------------------------------------------------------------------------------------------- | | `destination` | string | yes | Country codes defined by the [ISO 3166-2](https://en.wikipedia.org/wiki/ISO_3166-2) standard. | | `source` | string | no | If not provided, we will use your store's default shipping address. Country codes are defined by the [ISO 3166-2](https://en.wikipedia.org/wiki/ISO_3166-2) standard. | #### Body | Key | Type | Required | Value | | --------- | ------- | -------- | ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | | `parcels` | `array` | yes | The list of parcels. Possible values for parcel dimensions. Key Type Required Value `weight` number yes `2`. weight should be measured in kg. At the moment, only two digits are allowed after decimal. `height` number no `0.64`. height should be measured in meters. At the moment, only two digits are allowed after decimal. `width` number no `0.38`. the width should be measured in meters. At the moment, only two digits are allowed after decimal. `length` number no `0.39`. length should be measured in meters. At the moment, only two digits are allowed after decimal. | #### Example request ```shell curl -X 'POST' \'https://shipping.montonio.com/api/v2/shipping-methods/filter-by-parcels?destination=EE&source=EE' \ -H 'accept: application/json' \ -H 'Authorization: Bearer [your_token]' \ -H 'Content-Type: application/json' \ -d '{ "parcels": [{ "weight": 2, "length": 0.61, "height": 0.36, "width": 0.43 }] }' ``` Show / Hide Response Data ```json { "countries": [ { "carriers": [ { "carrierCode": "dpd", "shippingMethods": [ { "type": "courier", "constraints": { "parcelDimensionsRequired": false } }, { "type": "pickupPoint", "constraints": { "parcelDimensionsRequired": false } } ] }, { "carrierCode": "omniva", "shippingMethods": [ { "type": "courier", "constraints": { "parcelDimensionsRequired": false } }, { "type": "pickupPoint", "constraints": { "parcelDimensionsRequired": false } } ] }, { "carrierCode": "venipak", "shippingMethods": [ { "type": "courier", "constraints": { "parcelDimensionsRequired": false } }, { "type": "pickupPoint", "constraints": { "parcelDimensionsRequired": false } } ] } ], "countryCode": "EE" } ] } ``` #### Response codes | Http code | Description | | --------- | -------------------------------------------------------- | | `200` | Return all store shipping methods available for parcels. | #### Response fields The response structure is the same as the [GET /shipping-methods](#get-shipping-methods-for-a-store) endpoint. Each shipping method includes a `constraints` object with a `parcelDimensionsRequired` field. See the [Response fields](#response-fields) section above for details. ### Calculate shipping rates The endpoint allows you to **calculate shipping rates** for given parcels and destination. This is useful for displaying shipping costs to customers at checkout before creating a shipment. :::note\[Montonio Contract Required] This endpoint only returns rates for carriers with **Montonio contracts**. Carriers that only support Direct contracts will not be included in the response. To use this endpoint, ensure you have activated a Montonio contract for the carrier through the Partner System. ::: #### Endpoint path ```http POST /shipping-methods/rates ``` #### Authentication Refer to the [Authentication section](/api/shipping-v2/reference#authentication). Follow instructions for GET endpoints. #### Headers | Key | Required | Value | | ------------- | -------- | --------------------- | | Authorization | yes | `Bearer [your_token]` | #### Query Params | Key | Type | Required | Value | | -------------------- | ------ | -------- | ----------------------------------------------------------------- | | `carrierCode` | string | no | Filter by carrier code. | | `shippingMethodType` | string | no | Filter by shipping method type. Values: `courier`, `pickupPoint`. | #### Body | Key | Type | Required | Description | | ------------- | -------- | -------- | -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | | `destination` | `string` | yes | Destination country code (ISO 3166-2). | | `parcels` | `array` | yes | Array of parcels, each containing an `items` array. Key Type Required Description `items` array yes Array of items in the parcel. `items[].length` number yes Item length. `items[].width` number yes Item width. `items[].height` number yes Item height. `items[].dimensionUnit` string no Dimension unit: `cm` (default), `m`, `mm`. `items[].weight` number yes Item weight. `items[].weightUnit` string no Weight unit: `kg` (default), `g`. `items[].quantity` number no Item quantity. Default: 1. Max: 1000. | #### Example request ```shell curl -X 'POST' \ 'https://shipping.montonio.com/api/v2/shipping-methods/rates?shippingMethodType=pickupPoint' \ -H 'accept: application/json' \ -H 'Authorization: Bearer [your_token]' \ -H 'Content-Type: application/json' \ -d '{ "destination": "EE", "parcels": [ { "items": [ { "length": 20, "width": 15, "height": 10, "dimensionUnit": "cm", "weight": 0.5, "weightUnit": "kg", "quantity": 1 } ] } ] }' ``` Show / Hide Response Data ```json { "calculationDetails": { "estimatedParcels": [ { "length": 20, "width": 15, "height": 10, "dimensionUnit": "cm", "actualWeight": 0.5, "volumetricWeight": 0.75, "chargeableWeight": 0.75, "weightUnit": "kg", "bufferApplied": 0 } ] }, "destination": "EE", "carriers": [ { "carrierCode": "omniva", "shippingMethods": [ { "type": "pickupPoint", "subtypes": [ { "code": "parcelMachine", "rate": "2.50", "currency": "EUR" }, { "code": "postOffice", "rate": "2.50", "currency": "EUR" } ] } ] }, { "carrierCode": "dpd", "shippingMethods": [ { "type": "pickupPoint", "subtypes": [ { "code": "parcelMachine", "rate": "3.00", "currency": "EUR" }, { "code": "parcelShop", "rate": "3.00", "currency": "EUR" } ] } ] } ] } ``` #### Response codes | Http code | Description | | --------- | ---------------------------------------------------- | | `200` | Returns calculated rates for all available carriers. | #### Response fields | Key | Type | Description | | -------------------------------------------------------- | -------- | ------------------------------------------------- | | `calculationDetails` | `object` | Details about the parcel calculations. | | `calculationDetails.estimatedParcels` | `array` | Estimated measurements for each parcel. | | `calculationDetails.estimatedParcels[].actualWeight` | `number` | Actual weight in kg. | | `calculationDetails.estimatedParcels[].volumetricWeight` | `number` | Volumetric weight in kg. | | `calculationDetails.estimatedParcels[].chargeableWeight` | `number` | Chargeable weight (max of actual and volumetric). | | `calculationDetails.estimatedParcels[].bufferApplied` | `number` | Buffer percentage applied to height for stacking. | | `destination` | `string` | Destination country code. | | `carriers` | `array` | List of carriers with their rates. | | `carriers[].carrierCode` | `string` | Carrier code. | | `carriers[].shippingMethods` | `array` | Available shipping methods with rates. | | `carriers[].shippingMethods[].type` | `string` | Shipping method type: `courier` or `pickupPoint`. | | `carriers[].shippingMethods[].subtypes` | `array` | Subtypes with individual rates. | | `carriers[].shippingMethods[].subtypes[].code` | `string` | Subtype code (e.g., `parcelMachine`, `standard`). | | `carriers[].shippingMethods[].subtypes[].rate` | `string` | Rate formatted to 2 decimal places. | | `carriers[].shippingMethods[].subtypes[].currency` | `string` | Currency code (e.g., `EUR`). | | `carriers[].shippingMethods[].subtypes[].operators` | `array` | Available operators for this subtype (optional). | :::note Rates are calculated based on your store's contract pricing. When multiple items are in a parcel, heights are summed with a 15% buffer for stacking. ::: ### Create Shipment The endpoint allows you to **create a shipment for your store**. #### Endpoint path ```http POST /shipments ``` #### Authentication Refer to the [Authentication section](/api/shipping-v2/reference#authentication). Follow instructions for GET endpoints. #### Headers | Key | Required | Value | | ------------- | -------- | --------------------- | | Authorization | yes | `Bearer [your_token]` | #### Body | Key | Type | Required | Value | | ------------------- | --------- | -------- | -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | | `merchantReference` | `string` | no | Any reference or order ID that the merchant wants to use. | | `shippingMethod` | `object` | yes | An object that defines the shipping method and optional additional services. Key Type Required Value `type` stringyes Available values: `courier`, `pickupPoint`. `id` string yes The shipping method UUID (pickup point ID or courier service ID). `additionalServices` array no Optional additional services. See table below for structure. `parcelHandoverMethod` string no Unisend only. Values: `courierPickUp`, `terminalDropOff`. `lockerSize` string no Unisend only. Values: `XS`, `S`, `M`, `L`, `XL`. **Additional services structure:** Key Type Required Value `code` string yes Service type: `cod` (Cash on Delivery) or `ageVerification`. `params` object conditional Required for `cod`. Contains `amount` (number, 0.01-10000). | | `parcels` | `array` | yes | The list of parcels. Below are the properties for a single parcel Key Type Required Value `weight` number yes `2`. weight should be measured in kg. At the moment, only two digits are allowed after decimal. `height` number no `0.64`. height should be measured in meters. At the moment, only two digits are allowed after decimal. `width` number no `0.38`. width should be measured in meters. At the moment, only two digits are allowed after decimal. `length` number no `0.39`. length should be measured in meters. At the moment, only two digits are allowed after decimal. | | `receiver` | `object` | yes | Receiver information. Key Type Required Value `firstName` stringno receiver's first name. `lastName` string no receiver's last name. `name` string yes receiver's full name. `streetAddress` string conditional if shipping method is `courier` then it is mandatory. `locality` string conditional if shipping method is courier then it is mandatory. `postalCode` string conditional if shipping method is `courier` then it is mandatory. `country` string conditional if shipping method is `courier` then it is mandatory. `phoneCountryCode` string yes `372`. Represents the country code for the phone number. `phoneNumber` string yes `5555555`. Represents the phone number without the phone county code. `region` string no It represents the region of the address. `email` string no It represents the email address. `companyName` string no It represents company/business name of the receiver. | | `sender` | `object` | no | Sender information. Key Type Required Value `name` stringyes Represents sender's full name. `streetAddress` yes conditional Represents the street address of the sender. `locality` string yes Represents the locality of the sender. `postalCode` string yes Represents the postalCode of the address. `country` string yes country code for the address. `phoneCountryCode` string yes `372`. Represents the country code for the phone number. `phoneNumber` string yes `5555555`. Represents the phone number without the phone county code. `region` string no It represents the region of the address. `email` string no It represents the email address. `companyName` string no It represents company/business name of the receiver. | | `products` | `array` | no | List of shipped products. Adding products enables the pick list feature and displays products on the tracking page. Key Type Required Description `sku` string yes Product SKU identifier. Max 100 characters. `name` string yes Product name. Max 255 characters. `quantity` number yes Product quantity. Max value is 999. Decimals allowed. `barcode` string no Product barcode (any format). Max 100 characters. `price` number no Product unit price. Max 2 decimal places. `currency` string no ISO 4217 currency code (e.g., `EUR`, `USD`). `attributes` object no Custom attributes (e.g., `{"color": "Red", "size": "M"}`). Max 20 attributes. `imageUrl` string no URL to product image. Max 2048 characters. `storeProductUrl` string no URL to product page in your store. Max 2048 characters. `description` string no Product description. Max 5000 characters. HTML is stripped. | | `montonioOrderUuid` | `string` | no | The UUID received from Montonio as a response to creating an [order](/api/stargate/guides/orders). | | `orderComment` | `string` | no | Comment field, usually specified by customer. | | `synchronous` | `boolean` | no | When set to `true`, the shipment will be registered synchronously and the response will include the final registration status. When `false` or omitted, the shipment is queued for asynchronous processing and returns with status `pending`. Default: `false`. | :::note\[Additional Services Availability] Before including additional services in your shipment request, check their availability via the [/shipping-methods/pickup-points](#get-pickup-points-for-a-store) or [/shipping-methods/courier-services](#get-courier-services-for-a-store) endpoints. Each pickup point and courier service includes an `additionalServices` array listing the available services. ::: #### Example request ```shell curl -X 'POST' \ 'https://shipping.montonio.com/api/v2/shipments' \ -H 'accept: application/json' \ -H 'Authorization: Bearer [your_token]' \ -H 'Content-Type: application/json' \ -d '{ "sender": { "name": "Sender Y", "companyName": "Company Y", "streetAddress": "Kai 1", "locality": "Tallinn", "region": "Harjumaa", "postalCode": "10111", "country": "EE", "phoneCountryCode": "372", "phoneNumber": "53334770", "email": "support@montonio.com" }, "receiver": { "name": "Receiver X", "companyName": "Company X", "streetAddress": "Kai 11", "locality": "Tallinn", "region": "Harjumaa", "postalCode": "10111", "country": "EE", "phoneCountryCode": "372", "phoneNumber": "53334770", "email": "support@montonio.com" }, "merchantReference": "order 1", "shippingMethod": { "type": "courier", "id": "aeada198-fab7-4042-a414-82dcf3ea81e8", "additionalServices": [ { "code": "cod", "params": { "amount": 25.50 } } ] }, "parcels": [ { "weight": 1 } ], "products": [ { "sku": "product-123", "name": "Blue Police Car", "quantity": 3, "barcode": "0123456789123", "price": 19.99, "currency": "EUR", "attributes": { "color": "Blue", "material": "Plastic" }, "imageUrl": "https://example.com/images/blue-police-car.jpg" } ] }' ``` Show / Hide Response Data ```json { "id": "4c1f8213-eec0-4ee6-8661-613eca9dd27e", "createdAt": "2024-06-14T13:03:49.039Z", "status": "pending", "montonioOrderUuid": null, "merchantReference": "order 1", "sender": { "id": "cc10856d-9e7d-4f3b-988f-eee0c10e8df8", "name": "Sender Y", "companyName": "Company Y", "streetAddress": "Kai 1", "locality": "Tallinn", "region": "Harjumaa", "postalCode": "10111", "country": "EE", "phoneCountryCode": "372", "phoneNumber": "53334770", "email": "support@montonio.com" }, "receiver": { "id": "e75cf0f8-9417-456b-927b-1ac95bbbab49", "firstName": null, "lastName": null, "name": "Receiver X", "companyName": "Company X", "streetAddress": "Kai 11", "locality": "Tallinn", "region": "Harjumaa", "postalCode": "10111", "country": "EE", "phoneCountryCode": "372", "phoneNumber": "53334770", "email": "support@montonio.com" }, "parcels": [ { "id": "00b000c6-d694-4bb0-b1db-6159c45ffed2", "weight": 1, "length": null, "height": null, "width": null, "carrierParcelId": null, "trackingLink": null } ], "shippingMethod": { "id": "e61bef79-cfdc-462e-8d57-a77a0c54abba", "type": "pickupPoint", "carrierCode": "smartpost", "countryCode": "EE" }, "carrierShipmentId": null, "store": { "id": "5d165f67-184f-451a-b819-214aabe25c00" }, "products": [ { "id": "64e917de-b662-478a-b123-b0bd099369d6", "createdAt": "2025-01-17T13:34:40.124Z", "sku": "product-123", "name": "Blue Police Car", "barcode": "0123456789123", "quantity": 3 } ] } ``` #### Response codes | Http code | Description | | --------- | ----------------------------------------------- | | `201` | Shipment was successfully created. | | `409` | Shipment already exists. | | `500` | There was a problem with creating the shipment. | ### Update a shipment This endpoint allows you to **update a shipment**. A shipment can only be updated when it's in status **registrationFailed** or **registered**. It is currently not possible to update the shipment's products. #### Endpoint path ```http PATCH /shipments/{shipmentId} ``` #### Authentication Refer to the [Authentication section](/api/shipping-v2/reference#authentication). Follow instructions for GET endpoints. #### Headers | Key | Required | Value | | ------------- | -------- | --------------------- | | Authorization | yes | `Bearer [your_token]` | #### Params | Key | Type | Required | Value | | ------------ | -------- | -------- | -------------------------------------- | | `shipmentId` | `string` | yes | The unique identifier of the shipment. | #### Body | Key | Type | Required | Value | | ---------------- | -------- | -------- | -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | | `shippingMethod` | `object` | no | An object that defines the shipping method and optional additional services. See the [Create Shipment](#create-shipment) section for the full structure including `additionalServices`, `parcelHandoverMethod`, and `lockerSize`. | | `parcels` | `array` | no | The list of parcels. Below are the properties for a single parcel Key Type Required Value `weight` number yes `2`. weight should be measured in kg. At the moment, only two digits are allowed after decimal. `height` number no `0.64`. height should be measured in meters. At the moment, only two digits are allowed after decimal. `width` number no `0.38`. width should be measured in meters. At the moment, only two digits are allowed after decimal. `length` number no `0.39`. length should be measured in meters. At the moment, only two digits are allowed after decimal. | | `receiver` | `object` | no | Receiver information. Key Type Required Value `firstName` stringno receiver's first name. `lastName` string no receiver's last name. `name` string yes receiver's full name. `streetAddress` string conditional if shipping method is `courier` then it is mandatory. `locality` string conditional if shipping method is courier then it is mandatory. `postalCode` string conditional if shipping method is `courier` then it is mandatory. `country` string conditional if shipping method is `courier` then it is mandatory. `phoneCountryCode` string yes `372`. Represents the country code for the phone number. `phoneNumber` string yes `5555555`. Represents the phone number without the phone county code. `region` string no It represents the region of the address. `email` string no It represents the email address. `companyName` string no It represents company/business name of the receiver. | | `sender` | `object` | no | Sender information. Key Type Required Value `name` stringyes Represents sender's full name. `streetAddress` yes conditional Represents the street address of the sender. `locality` string yes Represents the locality of the sender. `postalCode` string yes Represents the postalCode of the address. `country` string yes country code for the address. `phoneCountryCode` string yes `372`. Represents the country code for the phone number. `phoneNumber` string yes `5555555`. Represents the phone number without the phone county code. `region` string no It represents the region of the address. `email` string no It represents the email address. `companyName` string no It represents company/business name of the receiver. | #### Example request ```shell curl -X 'PATCH' \ 'https://shipping.montonio.com/api/v2/shipments/7a6f087c-def0-4830-80af-55ccdf7df3fd' \ -H 'accept: application/json' \ -H 'Authorization: Bearer [your_token]' \ -H 'Content-Type: application/json' \ -d '{ "receiver": { "name": "New Name for Receiver", "companyName": "New Company Name", "streetAddress": "street no 2", "locality": "Tallinn", "region": "Harjumaa", "postalCode": "10999", "country": "EE", "phoneCountryCode": "372", "phoneNumber": "58107505", "email": "someone@montonio.com" } }' ``` Show / Hide Response Data ```json { "id": "7a6f087c-def0-4830-80af-55ccdf7df3fd", "createdAt": "2024-05-31T11:52:03.766Z", "status": "registered", "montonioOrderUuid": null, "merchantReference": "123456", "sender": { "id": "030ded90-16c3-44ad-a78a-15efaa298335", "name": "John", "companyName": "Smith", "streetAddress": "test street no 123", "locality": "Tallinn", "region": "Harjumaa", "postalCode": "10999", "country": "EE", "phoneCountryCode": "372", "phoneNumber": "55555555", "email": "someone@montonio.com" }, "receiver": { "id": "504590f8-79e9-40f9-81b7-3ff15095dbef", "name": "New Name for Receiver", "firstName": null, "lastName": null, "companyName": "New Company Name", "streetAddress": "street no 2", "locality": "Tallinn", "region": "Harjumaa", "postalCode": "10999", "country": "EE", "phoneCountryCode": "372", "phoneNumber": "58107505", "email": "someone@montonio.com" }, "parcels": [ { "id": "46ae777e-67fa-4e62-9c37-04222aaee810", "weight": 2, "length": null, "height": null, "width": null, "carrierParcelId": "CC543130987EE", "trackingLink": "https://minu.omniva.ee/track/CC543130987EE?language=et" } ], "shippingMethod": { "id": "0ffb9b04-3927-462a-a393-4f1e21f2ee55", "type": "courier", "carrierCode": "omniva", "countryCode": "EE" }, "carrierShipmentId": null, "store": { "id": "eb607940-7348-4ef7-a13f-d983c0637466" }, "products": null } ``` #### Response codes | Http code | Description | | --------- | ------------------------------------------------ | | `200` | Shipment was successfully updated. | | `500` | There was a problem while updating the shipment. | ### Get shipment details The endpoint allows you to **fetch the details of a shipment**. #### Endpoint path ```http GET /shipments/{shipmentId} ``` #### Authentication Refer to the [Authentication section](/api/shipping-v2/reference#authentication). Follow instructions for GET endpoints. #### Headers | Key | Required | Value | | ------------- | -------- | --------------------- | | Authorization | yes | `Bearer [your_token]` | #### Params | Key | Type | Required | Value | | ------------ | -------- | -------- | -------------------------------------- | | `shipmentId` | `string` | yes | The unique identifier of the shipment. | #### Example request ```shell curl -X 'GET' \ 'https://shipping.montonio.com/api/v2/shipments/d10e4ed8-1776-4828-bde7-0eb95456e367' \ -H 'accept: application/json' \ -H 'Authorization: Bearer [your_token]' ``` Show / Hide Response Data ```json { "id": "d10e4ed8-1776-4828-bde7-0eb95456e367", "createdAt": "2024-05-31T13:11:10.307Z", "status": "labelsCreated", "montonioOrderUuid": null, "merchantReference": "1213321", "sender": { "id": "5d61c57b-151c-44b8-98b8-2715570534ab", "name": "John", "companyName": "Smith", "streetAddress": "test street no 123", "locality": "Tallinn", "region": "Harjumaa", "postalCode": "10999", "country": "EE", "phoneCountryCode": "372", "phoneNumber": "55555555", "email": "someone@montonio.com" }, "receiver": { "id": "fb424f5d-acc8-4cf8-a21b-cecb5c3daacf", "firstName": "Joe", "lastName": "Smith", "companyName": "", "streetAddress": "test street", "locality": "tallinn", "region": "", "postalCode": "10615", "country": "EE", "phoneCountryCode": "372", "phoneNumber": "58107505", "email": "someone@montonio.com" }, "parcels": [ { "id": "0a3533e6-6a8c-4dfa-83b6-df76f8f74372", "weight": 2, "length": null, "height": null, "width": null, "carrierParcelId": "CC543167770EE", "trackingLink": "https://minu.omniva.ee/track/CC543167770EE?language=et" } ], "shippingMethod": { "id": "98b391d7-5299-447c-9ad7-6b4042ef8b2f", "type": "pickupPoint", "carrierCode": "omniva", "countryCode": "EE" }, "carrierShipmentId": null, "store": { "id": "eb607940-7348-4ef7-a13f-d983c0637466" }, "products": null } ``` #### Response codes | Http code | Description | | --------- | ----------------------------- | | `200` | Returns the shipment details. | | `404` | Shipment not found. | ### Create a label file The endpoint allows you to **create a label file for your shipments**. :::note Once the label is created, the label URL will last 5 minutes, after which it will no longer be accessible. To get a fresh URL, make a new request. ::: #### Endpoint path ```http POST /label-files ``` #### Authentication Refer to the [Authentication section](/api/shipping-v2/reference#authentication). Follow instructions for GET endpoints. #### Headers | Key | Required | Value | | ------------- | -------- | --------------------- | | Authorization | yes | `Bearer [your_token]` | #### Body | Key | Type | Required | Value | | --------------- | --------- | -------- | --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | | `shipmentIds` | `array` | yes | An array of shipment ids. | | `pageSize` | `string` | no | Available values: `A4`, `A6`. | | `labelsPerPage` | `number` | no | Available values: `1`, `4`, `6`, `8`. | | `orderLabelsBy` | `string` | no | Available values: `carrier`, `createdAt`. | | `synchronous` | `boolean` | no | When set to `true`, the label file will be generated synchronously and the response will include the download URL. When `false` or omitted, label generation is queued and returns with status `pending`. Default: `false`. | #### Example request ```shell curl -X 'POST' \ 'https://shipping.montonio.com/api/v2/label-files' \ -H 'Authorization: Bearer [your_token]' \ -H 'Content-Type: application/json' \ -d '{ "shipmentIds": [ "d10e4ed8-1776-4828-bde7-0eb95456e367" ], "pageSize": "A4", "labelsPerPage": 1, "orderLabelsBy": "carrier" }' ``` Show / Hide Response Data ```json { "id": "44cb7cbf-8ac9-48b8-ba9c-2162f8420885", "status": "pending", "pageSize": "A4", "labelsPerPage": "1", "orderLabelsBy": "carrier", "labelFileUrl": null } ``` #### Response codes | Http code | Description | | --------- | -------------------------------------------- | | `201` | Shipping labels were successfully created. | | `400` | Bad request, validation failed. | | `500` | There was a problem creating the label file. | ### Get label file The endpoint allows you to **fetch the label file**. :::note Once the label is created, the label URL will last 5 minutes, after which it will no longer be accessible. To get a fresh URL, make a new request. ::: #### Endpoint path ```http GET /label-files/{labelFileId} ``` #### Authentication Refer to the [Authentication section](/api/shipping-v2/reference#authentication). Follow instructions for GET endpoints. #### Headers | Key | Required | Value | | ------------- | -------- | --------------------- | | Authorization | yes | `Bearer [your_token]` | #### Params | Key | Type | Required | Value | | ------------- | -------- | -------- | ------------------------- | | `labelFileId` | `string` | yes | The ID of the label file. | #### Example request ```shell curl -X 'GET' \ 'https://shipping.montonio.com/api/v2/label-files/7e30e74e-88be-4ab6-a972-649993a616e1' \ -H 'accept: application/json' \ -H 'Authorization: Bearer [your_token]' ``` Show / Hide Response Data ```json { "id": "7e30e74e-88be-4ab6-a972-649993a616e1", "status": "ready", "pageSize": "A4", "labelsPerPage": "1", "orderLabelsBy": "carrier", "labelFileUrl": "https://shipping-v2-labels-production-s3.s3.eu-central-1.amazonaws.com/5decd9b6-4fa2-47cf-b045-d67444a8892a?X-Amz-Algorithm=AWS4-HMAC-SHA256&X-Amz-Content-Sha256=UNSIGNED-PAYLOAD&X-Amz-Credential=ASIAXYMK66KJLORP5MVF%2F20240531%2Feu-central-1%2Fs3%2Faws4_request&X-Amz-Date=20240531T135149Z&X-Amz-Expires=300&X-Amz-Security-Token=IQoJb3JpZ2luX2VjEL3%2F%2F%2F%2F%2F%2F%2F%2F%2F%2FwEaDGV1LWNlbnRyYWwtMSJHMEUCIQDF0oYutWCaemuHRqKYK5nU3jkpb%2B4qlw91JLncABxzTQIgC6x5%2FBygSr0P8EEM%2BovhK4ejFO6K6IYsDtgpeU5oDUwq%2FgMIRxAAGgw1MzM0MDQyNTA3NzAiDEtk3DBxTr%2FeHcN%2F%2BSrbAxSJRJFElx4FEA4SmZNGbWQFQ6rer7Aare6c4uz23jEh1NJmZwubln9DMcRJ4eJu0MRJDADPJ4f1UFSRiLR7DamIyIYmWfxRt59DzLxwPM%2BfBPSqtjyWmSZGzlo4i4YTdJsMBNJjBcqrpCNqUjPPbLnzsEXfD%2F%2FC4FvdE0vri9lkNXB1n5Y1w9UmIiUjBbRpNpcP%2F1ECjElLq0OmewNMGsEYUA657YrnzAWvs8twp3kXN37l2KDWrIr5UDMBMvdKDa9%2BUQ2iTrzu2l1picGTRVZT%2BwHd5EmgSUWIYM%2BEMqRYbUPVolRkNoM4%2BYRSjGMyIvMkLoRllUMGCEjqYSQXezOHS%2BpkyebZ%2B4w4O1O64Eq5KqDH9lxMuvniAyvkvZL3WdeAOnKQHb9xOvsbxnHq3iEQQrnsyy7x98TpGqHAC0usnc6qDXrmNSDF5aogqOyVOzxfHQYp9nelDEIiSftH%2BeNUK2Bc0Nuy9InN2ugJ4DtCX4jBHidAoG3cQGSjZkHIXrs%2BRbxjy%2FOQ8RIO5YLZa1DiPf%2Fu%2BliAbVQsWR0ePGglfwQGMhUyrv3OM7%2Bcwe89o12raE2H2gy8Dcdlvwq9Ug2aoUCBaK755lY27sG5Ff4uFs3LxvsdqFd%2FnIIwv57nsgY6pQFTLH1wBVgy4Dgv7yUwqy2zthGlLAHPP3prKsnxhR6tydf9rB3isapsW3AJhy28buXPvKv0beYb5vteRsnIUybX8NPil7oWO6B8Z%2FDWVfzeZ0uw3tK%2BK4mAwtMAXvBjd73HX14NQ92OSp82tNzn8%2BwDt9aJjv7FKA8YY2fAM4Vl70rwL8j0VIlD9L6w%2BEcbNIurwNSIMPrHFMA3nFFogEB3muRcf0M%3D&X-Amz-Signature=da12ce556539809a27a053576b1831b4d8df2eec5de4f2013944154ad33c1fc2&X-Amz-SignedHeaders=host&x-id=GetObject" } ``` #### Response codes | Http code | Description | | --------- | ------------------------------------------- | | `200` | Return the label file details. | | `500` | There was a problem getting the label file. | ### Create webhooks The endpoint allows you to create a webhook that can be used to subscribe to different events, such as `shipment.registered`, `shipment.registrationFailed`, `shipment.labelsCreated`, `shipment.statusUpdated`, `labelFile.ready` and `labelFile.creationFailed`. #### Endpoint path ```http POST /webhooks ``` #### Authentication Refer to the [Authentication section](/api/shipping-v2/reference#authentication). Follow instructions for GET endpoints. #### Headers | Key | Required | Value | | ------------- | -------- | --------------------- | | Authorization | yes | `Bearer [your_token]` | #### Body | Key | Type | Required | Value | | --------------- | -------- | -------- | -------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | | `url` | `string` | yes | The notification URL for receiving updates. | | `enabledEvents` | `array` | yes | Available values: `shipment.registered`, `shipment.registrationFailed`, `shipment.labelsCreated`, `shipment.statusUpdated`, `labelFile.ready`, `labelFile.creationFailed`. | #### Example request ```shell curl -X 'POST' \ 'https://shipping.montonio.com/api/v2/webhooks' \ -H 'accept: application/json' \ -H 'Authorization: Bearer [your_token]' \ -H 'Content-Type: application/json' \ -d '{ "url": "http://partner.montonio/shipmentEvents", "enabledEvents": ["shipment.registered"] }' ``` Show / Hide Response Data ```json { "id": "92965086-24a3-4fbd-919a-661142210c48", "createdAt": "2024-05-31T14:02:47.780Z", "url": "http://partner.montonio/shipmentEvents", "enabledEvents": [ "shipment.registered" ] } ``` #### Response codes | Http code | Description | | --------- | -------------------------------------------------------------------------------------------- | | `201` | Webhook was successfully created. | | `400` | Bad request, validation failed. | | `403` | Webhook limit has been reached. You can currently create a maximum of 10 webhooks per store. | | `409` | Webhook already exists. | | `500` | There was a problem creating the webhook. | ### Get all webhooks The endpoint allows you to **fetch all webhooks created for your store**. #### Endpoint path ```http GET /webhooks ``` #### Authentication Refer to the [Authentication section](/api/shipping-v2/reference#authentication). Follow instructions for GET endpoints. #### Headers | Key | Required | Value | | ------------- | -------- | --------------------- | | Authorization | yes | `Bearer [your_token]` | #### Example request ```shell curl -X 'GET' \ 'https://shipping.montonio.com/api/v2/webhooks' \ -H 'accept: application/json' \ -H 'Authorization: Bearer [your_token]' ``` Show / Hide Response Data ```json { "data": [ { "id": "92965086-24a3-4fbd-919a-661142210c48", "createdAt": "2024-05-31T14:02:47.780Z", "url": "http://partner.montonio/shipmentEvents", "enabledEvents": [ "shipment.registered" ] } ] } ``` #### Response codes | Http code | Description | | --------- | ------------------------------------------- | | `200` | Returns the list of webhooks for the store. | | `500` | There was a problem fetching the webhooks. | ### Delete a webhook The endpoint allows you to **delete a webhook**. #### Endpoint path ```http DELETE /webhooks/{webHookId} ``` #### Authentication Refer to the [Authentication section](/api/shipping-v2/reference#authentication). Follow instructions for GET endpoints. #### Headers | Key | Required | Value | | ------------- | -------- | --------------------- | | Authorization | yes | `Bearer [your_token]` | #### Params | Key | Required | Value | | ----------- | -------- | ----------------------------- | | `webHookId` | yes | It represents the webhook id. | #### Example request ```shell curl -X 'DELETE' \ 'https://shipping.montonio.com/api/v2/webhooks/8724ef8b-aca4-4a2f-bf5b-074118f9adf6' \ -H 'accept: application/json' \ -H 'Authorization: Bearer [your_token]' ``` Show / Hide Response Data ```json 200 Ok {} ``` #### Response codes | Http code | Description | | --------- | ----------------------------------------- | | `200` | Webhook deleted successfully. | | `400` | Bad request, validation failed. | | `500` | There was a problem deleting the webhook. | --- # API changes URL: /api/stargate/changes ## Backwards-compatible changes The following is a list of changes we consider to be backwards-compatible. Such changes to the API will be made without advance notice. - Adding new endpoints. - Adding new optional request parameters to existing endpoints. - Adding new properties to existing response objects. - Adding new enum values to existing enums. - Adding new error codes. - Changing the order of properties in existing request and response objects. --- # Integration checklist URL: /api/stargate/checklist ## Sign up for an account 1. Create your Montonio account by filling in the registration form on our website (click the "Get started" button) and complete the onboarding in our Partner System. 2. Create a Partner System user account for yourself and other team members who are working on the integration. 3. Copy the API keys of your store from the Partner System. ## Let your customer choose a payment method Full guide: [Display payment methods](/api/stargate/guides/payment-methods) 1. Get the list of available payment methods from the API. 2. Display the list of available payment methods to the customer. ## Create an Order and redirect the customer Full guide: [Create and validate an order](/api/stargate/guides/orders) 1. Compose a JWT with the Order details and sign it with your `Secret Key`. 2. Create an Order by sending the JWT to the `POST /orders` endpoint. 3. Redirect the customer to the `paymentUrl` returned by the API. 4. After your customer finishes the payment process, he will be redirected to the `returnUrl` specefied in your request. ## Validate the payment Full guide: [Create and validate an order -> Validating the payment](/api/stargate/guides/orders#validating-the-payment) Montonio uses webhooks to notify you about Order status changes, events related to refunds, and other important events. **It is required to listen to webhooks by specifying `notificationUrl` to keep your Order statuses up to date.** Additionally, an Order token with the same information is included as a query parameter during the redirect back to your store. This helps you validate the payment as part of the synchronous user flow. However, webhooks should still be the primary method of listening for Order status changes. 1. Set up a webhook listener on your server. 2. Wait for the event. 3. Verify the contents of the webhook with your `Secret Key`. 4. Update the status of the Order in your system and take any other necessary actions. --- # Payments URL: /api/stargate --- # Payments URL: /api/stargate/overview To accept payments with Montonio, you need to integrate with our Stargate API. In the [Guides](/api/stargate/guides) section, you can find detailed instructions on how to integrate with the API, along with code examples in various programming languages. :::note Before starting the integration, we recommend you to familiarize yourself with the basic concepts of the API, which are described below. ::: ## What is an Order? When you integrate with Montonio, you'll be working with a set of objects which are used to represent the payment process. The most important and central object is the **Order**. To accept payments, you must first [create an Order](/api/stargate/guides/orders), ideally matching one-to-one with an Order object in your e-commerce, ERP, or accounting system. The Order object contains all the information needed to process a payment, such as the amount, currency, preferred payment method, the customer's email address, etc. ## What payment methods can be used? An Order can be paid for using one of the available payment methods, which is specified when creating the Order. The available payment methods per currency are: | Payment method | Supported currencies | System name | | --------------------- | -------------------- | ------------------- | | **Bank Payments** | `EUR`, `PLN` | `paymentInitiation` | | **Card Payments** | `EUR`, `PLN` | `cardPayments` | | **MobilePay** | `EUR` | `mobilePay` | | **BLIK** | `PLN` | `blik` | | **Buy Now Pay Later** | `EUR` | `bnpl` | | **Hire Purchase** | `EUR` | `hirePurchase` | ## What is the lifecycle of an Order? In order to communicate the status of a payment we use the Order's `paymentStatus`. Whenever an order transitions from one status to another you will receive a webhook (HTTP POST request). You can expect the following values for `paymentStatus`: | Status | Available by default | Description | | ----------------------- | -------------------- | -------------------------------------------------------------------------------------------------------------------------------------------------------- | | **PENDING** | ✅ YES | Order is created but the payment is not yet completed by the customer. This is the first status of an Order. | | **PAID** | ✅ YES | Order has been paid for by the customer. | | **VOIDED** | ✅ YES | An order previously marked as PAID was rejected by the bank1 An email is sent to the merchant's contact address to inform you of this exceptional case. | | **PARTIALLY\_REFUNDED** | ✅ YES | Order amount has been partially refunded. | | **REFUNDED** | ✅ YES | Order amount has been fully refunded. | | **ABANDONED** | ✅ YES2 | When an order is PENDING for a certain duration (30 minutes by default) we will update the order status to ABANDONED and send a webhook. | | **AUTHORIZED** | ❌ Opt in3 | Intermediate status for `paymentInitiation` payments indicating that the payment is signed by the customer but not yet processed by the bank. | References: 1. A PAID order becoming VOIDED can only happen with the `paymentInitiation` payment method. It's a rare edge case for when the customer's bank experienced technical issues or rejected the payment for suspicious activity. Read more about it in [this article](https://help.montonio.com/en/articles/286378-voided-payments-why-do-they-happen). 2. The `ABANDONED` status is enabled for merchants who started using Montonio after 2023.08.29. Contact Customer Support to enable this feature if you joined before 2023.08.29. 3. Feature available only for select enterprise customers. ## What is the lifecycle of a Refund? In order to communicate the status of a refund we use the Refund's `status`. You can expect the following values for `status`: | Status | Description | | -------------- | ----------------------------------------------------------------------------------------------- | | **PENDING** | Refund has been created but not yet processed. This is the first status of a Refund. | | **PROCESSING** | Refund has been submitted for processing. The funds are being transferred back to the customer. | | **SUCCESSFUL** | Refund has been successfully processed and the funds have been returned to the customer. | | **REJECTED** | Refund was rejected and could not be completed. | | **CANCELED** | Refund was cancelled before processing. | ## How to access the API? > The API Base URLs for the available environments are as follows: > > - **Production**: `https://stargate.montonio.com/api` > - **Sandbox**: `https://sandbox-stargate.montonio.com/api` To authenticate with the API, you'll need to use API keys. Read more about [API keys](/introduction#api-keys) and how to get them. The authentication mechanism is described in the [Authentication section](/api/stargate/reference#authentication) of the API reference. ## Getting started The best way to get started is to first read the [Integration checklist](/api/stargate/checklist). Once you're familiar with the flow, dive deeper into the [Developer guides](/api/stargate/guides) to build your integration step-by-step. Happy integrating! 🚀 --- # API reference URL: /api/stargate/reference ## API URLs API Base URLs for the available environments are as follows: > - **Production**: `https://stargate.montonio.com/api` > - **Sandbox**: `https://sandbox-stargate.montonio.com/api` ## Authentication The Stargate API uses [JWT (JSON Web Tokens)](https://jwt.io/) for authentication. `GET` endpoints require a JWT in the `Authorization` header. `POST` endpoints require that the request payload is the JWT and the token itself contains the original request data. Both `GET` and `POST` JWTs must contain your `Access Key` and be signed with your `Secret Key` using HMAC SHA256 (HS256). Read more about [API keys here](/introduction#api-keys). The exact implementation of how to generate the JWT varies by programming language and you can see some examples on the code panel of some of the guides. We recommend using popular community maintained libraries for generating and verifying JWTs. To learn more about JWTs, find libraries for your programming language, or to debug and verify your JWTs, visit [jwt.io](https://jwt.io/). ### JWT headers | Key | Required | Type | Description | | --- | -------- | -------- | ---------------------- | | alg | yes | `string` | Must be set to `HS256` | | typ | yes | `string` | Must be set to `JWT` | ### JWT payload Here is the minimum required payload for all requests: | Key | Required | Type | Description | | --------- | -------- | -------- | ------------------------------------------------------------------------------------------------------------------ | | accessKey | yes | `string` | Your `Access Key` obtained from the Partner System. | | exp | yes | `number` | Expiration time of the token in Unix time. We recommend setting this to 1 hour from the time of issuing the token. | ```javascript /** * We recommend using the jsonwebtoken package to generate * Json Web Tokens. You can install it with npm: * > npm install jsonwebtoken * More information can be found at * https://www.npmjs.com/package/jsonwebtoken */ import jwt from 'jsonwebtoken'; const payload = { accessKey: 'MY_ACCESS_KEY' }; const authHeader = jwt.sign( payload, 'MY_SECRET_KEY', { algorithm: 'HS256', expiresIn: '1h' } ); console.log(authHeader); // eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJhY2Nlc3NLZXkiOiJNWV9BQ0NFU1NfS0VZIiwiaWF0IjoxNjc1OTM4NjM3LCJleHAiOjE2NzU5NDIyMzd9.f-wXP8t5HGhr5XKAl3eCeWbHnY3SO9DcY5WiWo06-uQ ``` ```php composer require firebase/php-jwt * More information can be found at * https://github.com/firebase/php-jwt */ // Should be loaded only once in the app, check composer docs for the specific framework you are using require __DIR__ . '/vendor/autoload.php'; use \Firebase\JWT\JWT; $payload = [ 'accessKey' => 'MY_ACCESS_KEY', 'iat' => time(), 'exp' => time() + (60 * 60) ]; $token = JWT::encode($payload, 'MY_SECRET_KEY', 'HS256'); // var_dump($token); // eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.eyJhY2Nlc3NLZXkiOiJNWV9BQ0NFU1NfS0VZIiwiaWF0IjoxNjc2MDQ1NTg5LCJleHAiOjE2NzYwNDkxODl9.9kz7LBZZVJrJbSO_42NTTg1Wg4HEP01cqOw0IzQ0nXU ``` ```python ''' We recommend using the PyJWT package to generate Json Web Tokens. You can install it with pip: > pip3 install PyJWT datetime More information can be found at https://pyjwt.readthedocs.io/en/latest/ ''' import jwt from datetime import datetime, timedelta, timezone payload = { 'accessKey': 'MY_ACCESS_KEY', 'iat': datetime.now(timezone.utc), 'exp': datetime.now(timezone.utc) + timedelta(hours=1) } auth_header = jwt.encode( payload, 'MY_SECRET_KEY', algorithm='HS256' ) print(auth_header) # eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJhY2Nlc3Nfa2V5IjoibWVyY2hhbnRfYWNjZXNzX2tleSIsImlhdCI6MTYwMzcxMTQ3NSwiZXhwIjoxNjAzNzE1MDc1fQ.UYwRQXykcIVNzIjni3icf_FBbxSXZ_m-2SsFfz3zjBs ``` ## API endpoints ### Get available payment methods The endpoint allows you to fetch **all enabled payment methods for your store**. This allows you to display the methods in your checkout and to let the customer choose their preferred payment method. In addition to the overall payment methods, the endpoint also returns a list of additional options for that method. For example, `paymentInitiation` will have a list of available banks, so that you can let the customer make their bank selection already in your checkout. #### Endpoint path ```http GET /stores/payment-methods ``` #### Authentication Refer to the [Authentication section](/api/stargate/reference#authentication). Follow instructions for GET endpoints. #### Headers | Key | Required | Value | | ------------- | -------- | --------------------- | | Authorization | yes | `Bearer [your_token]` | #### Example request ```shell curl -X GET \ 'https://stargate.montonio.com/api/stores/payment-methods' \ -H 'Authorization: Bearer eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJhY2Nlc3NLZXkiOiJNWV9BQ0NFU1NfS0VZIiwiaWF0IjoxNjc1OTM4NjM3LCJleHAiOjE2NzU5NDIyMzd9.f-wXP8t5HGhr5XKAl3eCeWbHnY3SO9DcY5WiWo06-uQ' ``` #### Example response Show / Hide Response Data ```json { "id": "0bafe86b-c5cf-4c88-ba28-484a8585f0f4", "name": "Montonio Store", "paymentMethods": { "blik": { "processor": "blik", "logoUrl": "https://public.montonio.com/images/logos/blik.png" }, "cardPayments": { "processor": "adyen", "logoUrl": "https://public.montonio.com/images/logos/visa-mc-ap-gp.png", "requiredToBeEnabled": true }, "mobilePay": { "processor": "adyen", "logoUrl": "https://public.montonio.com/images/logos/mobilepay.png", "requiredToBeEnabled": true }, "bnpl": { "processor": "inbank", "logoUrl": "https://public.montonio.com/images/logos/inbank_bnpl.png" }, "hirePurchase": { "processor": "inbank", "logoUrl": "https://public.montonio.com/images/logos/inbank_hire_purchase.png" }, "paymentInitiation": { "processor": "montonio", "setup": { "EE": { "supportedCurrencies": [ "EUR" ], "paymentMethods": [ { "code": "HABAEE2X", "name": "Swedbank Eesti", "logoUrl": "https://public.montonio.com/images/aspsps_logos/swedbank.png", "supportedCurrencies": [ "EUR" ] }, { "code": "EEUHEE2X", "name": "SEB Eesti", "logoUrl": "https://public.montonio.com/images/aspsps_logos/seb.png", "supportedCurrencies": [ "EUR" ] }, { "code": "LHVBEE22", "name": "LHV", "logoUrl": "https://public.montonio.com/images/aspsps_logos/lhv.png", "supportedCurrencies": [ "EUR" ] }, { "code": "RIKOEE22", "name": "Luminor Eesti", "logoUrl": "https://public.montonio.com/images/aspsps_logos/luminor.png", "supportedCurrencies": [ "EUR" ] }, { "code": "EKRDEE22", "name": "Coop Pank", "logoUrl": "https://public.montonio.com/images/aspsps_logos/coop.png", "supportedCurrencies": [ "EUR" ] }, { "code": "PARXEE22", "name": "Citadele Eesti", "logoUrl": "https://public.montonio.com/images/aspsps_logos/citadele.png", "supportedCurrencies": [ "EUR" ] }, { "code": "RVUALT2V", "name": "Revolut", "logoUrl": "https://public.montonio.com/images/aspsps_logos/revolut.png", "supportedCurrencies": [ "EUR", "PLN" ] } ] }, "FI": { "supportedCurrencies": [ "EUR" ], "paymentMethods": [ { "code": "OKOYFIHH", "name": "OP", "logoUrl": "https://public.montonio.com/images/aspsps_logos/op.png", "supportedCurrencies": [ "EUR" ] }, { "code": "NDEAFIHH", "name": "Nordea", "logoUrl": "https://public.montonio.com/images/aspsps_logos/nordea.png", "supportedCurrencies": [ "EUR" ] }, { "code": "DABAFIHH", "name": "Danske Bank", "logoUrl": "https://public.montonio.com/images/aspsps_logos/danske.png", "supportedCurrencies": [ "EUR" ] }, { "code": "ITELFIHH", "name": "Säästöpankki", "logoUrl": "https://public.montonio.com/images/aspsps_logos/saastopankki.png", "supportedCurrencies": [ "EUR" ] }, { "code": "POPFFI22", "name": "POP Pankki", "logoUrl": "https://public.montonio.com/images/aspsps_logos/pop.png", "supportedCurrencies": [ "EUR" ] }, { "code": "ITELFIHH", "name": "Oma Säästöpankki", "logoUrl": "https://public.montonio.com/images/aspsps_logos/omasp.png", "supportedCurrencies": [ "EUR" ] }, { "code": "SBANFIHH", "name": "S-Pankki", "logoUrl": "https://public.montonio.com/images/aspsps_logos/s-pankki.png", "supportedCurrencies": [ "EUR" ] }, { "code": "AABAFI22", "name": "Alandsbanken", "logoUrl": "https://public.montonio.com/images/aspsps_logos/alandsbanken-fi.png", "supportedCurrencies": [ "EUR" ] }, { "code": "RVUALT2V", "name": "Revolut", "logoUrl": "https://public.montonio.com/images/aspsps_logos/revolut.png", "supportedCurrencies": [ "EUR", "PLN" ] } ] }, "LV": { "supportedCurrencies": [ "EUR" ], "paymentMethods": [ { "code": "HABALV22", "name": "Swedbank Latvija", "logoUrl": "https://public.montonio.com/images/aspsps_logos/swedbank.png", "supportedCurrencies": [ "EUR" ] }, { "code": "UNLALV2X", "name": "SEB Latvija", "logoUrl": "https://public.montonio.com/images/aspsps_logos/seb.png", "supportedCurrencies": [ "EUR" ] }, { "code": "PARXLV22", "name": "Citadele Latvija", "logoUrl": "https://public.montonio.com/images/aspsps_logos/citadele.png", "supportedCurrencies": [ "EUR" ] }, { "code": "RIKOLV2X", "name": "Luminor Latvija", "logoUrl": "https://public.montonio.com/images/aspsps_logos/luminor.png", "supportedCurrencies": [ "EUR" ] }, { "code": "RVUALT2V", "name": "Revolut", "logoUrl": "https://public.montonio.com/images/aspsps_logos/revolut.png", "supportedCurrencies": [ "EUR", "PLN" ] } ] }, "LT": { "supportedCurrencies": [ "EUR" ], "paymentMethods": [ { "code": "HABALT22", "name": "Swedbank Lietuva", "logoUrl": "https://public.montonio.com/images/aspsps_logos/swedbank.png", "supportedCurrencies": [ "EUR" ] }, { "code": "CBVILT2X", "name": "SEB Lietuva", "logoUrl": "https://public.montonio.com/images/aspsps_logos/seb.png", "supportedCurrencies": [ "EUR" ] }, { "code": "AGBLLT2X", "name": "Luminor Lietuva", "logoUrl": "https://public.montonio.com/images/aspsps_logos/luminor.png", "supportedCurrencies": [ "EUR" ] }, { "code": "CBSBLT26", "name": "Šiaulių bankas", "logoUrl": "https://public.montonio.com/images/aspsps_logos/siauliu.png", "supportedCurrencies": [ "EUR" ] }, { "code": "MDBALT22", "name": "Medicinos bankas", "logoUrl": "https://public.montonio.com/images/aspsps_logos/medicinos.png", "supportedCurrencies": [ "EUR" ] }, { "code": "INDULT2X", "name": "Citadele Lietuva", "logoUrl": "https://public.montonio.com/images/aspsps_logos/citadele.png", "supportedCurrencies": [ "EUR" ] }, { "code": "RVUALT2V", "name": "Revolut", "logoUrl": "https://public.montonio.com/images/aspsps_logos/revolut.png", "supportedCurrencies": [ "EUR", "PLN" ] } ] }, "PL": { "supportedCurrencies": [ "PLN" ], "paymentMethods": [ { "code": "BPKOPLPW", "name": "PKO Bank Polski", "logoUrl": "https://public.montonio.com/images/aspsps_logos/pko-polski.png", "supportedCurrencies": [ "PLN" ] }, { "code": "PKOPPLPW", "name": "Bank Pekao", "logoUrl": "https://public.montonio.com/images/aspsps_logos/pekao.png", "supportedCurrencies": [ "PLN" ] }, { "code": "BREXPLPW", "name": "mBank", "logoUrl": "https://public.montonio.com/images/aspsps_logos/mbank.png", "supportedCurrencies": [ "PLN" ] }, { "code": "WBKPPLPP", "name": "Santander", "logoUrl": "https://public.montonio.com/images/aspsps_logos/santander.png", "supportedCurrencies": [ "PLN" ] }, { "code": "INGBPLPW", "name": "Ing", "logoUrl": "https://public.montonio.com/images/aspsps_logos/ing.png", "supportedCurrencies": [ "PLN" ] }, { "code": "ALBPPLPW", "name": "Alior", "logoUrl": "https://public.montonio.com/images/aspsps_logos/alior.png", "supportedCurrencies": [ "PLN" ] }, { "code": "PPABPLPK", "name": "BNP Paribas", "logoUrl": "https://public.montonio.com/images/aspsps_logos/bnp-paribas.png", "supportedCurrencies": [ "PLN" ] }, { "code": "BIGBPLPW", "name": "Millennium Bank", "logoUrl": "https://public.montonio.com/images/aspsps_logos/millennium.png", "supportedCurrencies": [ "PLN" ] }, { "code": "IBNKPAPA", "name": "Inteligo", "logoUrl": "https://public.montonio.com/images/aspsps_logos/inteligo.png", "supportedCurrencies": [ "PLN" ] }, { "code": "AGRIPLPR", "name": "Crédit Agricole", "logoUrl": "https://public.montonio.com/images/aspsps_logos/credit-agricole.png", "supportedCurrencies": [ "PLN" ] }, { "code": "RVUALT2V", "name": "Revolut", "logoUrl": "https://public.montonio.com/images/aspsps_logos/revolut.png", "supportedCurrencies": [ "EUR", "PLN" ] } ] } } } } } ``` ### Get Order by UUID The endpoint returns details about the order and its `paymentStatus`. You can use it to double-check the status of the order and its payment. In order to use this endpoint, you need to save the Order UUID returned by the `POST /orders` endpoint in your database. #### Endpoint path ```http GET /orders/:orderUuid ``` #### Authentication Refer to the [Authentication section](/api/stargate/reference#authentication). Follow instructions for GET endpoints. #### Headers | Key | Required | Value | | ------------- | -------- | --------------------- | | Authorization | yes | `Bearer [your_token]` | #### Example Request ```shell curl -X GET \ 'https://stargate.montonio.com/api/orders/0ac2124d-9f8e-4a29-816d-7eef5b9bb0fd' \ -H 'Authorization: Bearer eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJhY2Nlc3NLZXkiOiJNWV9BQ0NFU1NfS0VZIiwiaWF0IjoxNjc1OTM4NjM3LCJleHAiOjE2NzU5NDIyMzd9.f-wXP8t5HGhr5XKAl3eCeWbHnY3SO9DcY5WiWo06-uQ' ``` #### Example Response Show / Hide Response Data ```json { "uuid": "0ac2124d-9f8e-4a29-816d-7eef5b9bb0fd", "paymentStatus": "PARTIALLY_REFUNDED", "locale": "et", "merchantReference": "MY-ORDER-ID-123", "merchantReferenceDisplay": "MY-ORDER-ID-123", "merchantReturnUrl": "https://mystore.com/payment/return", "merchantNotificationUrl": "https://mystore.com/payment/notify", "grandTotal": "100.00", "currency": "EUR", "paymentMethodType": "cardPayments", "paymentIntents": [ { "uuid": "293513c0-66b1-401a-8afa-75e1f5714516", "paymentMethodType": "cardPayments", "paymentMethodMetadata": {}, "amount": "100.00", "currency": "EUR", "status": "PAID", "serviceFee": "3.15", // Montonio's transaction processing fee. Initially null during order creation, populated after payment processing completes "serviceFeeCurrency": "EUR", "createdAt": "2023-05-23T08:22:53.899Z" } ], "refunds": [ { "uuid": "92b11684-319a-4cce-92f5-56d348aa986a", "amount": "25", "status": "SUCCESSFUL", "currency": "EUR", "createdAt": "2023-05-23T08:37:55.534Z", "type": "PARTIAL_REFUND" }, { "uuid": "8453465a-a9d8-469e-a838-5b2b5b20f429", "amount": "25", "status": "SUCCESSFUL", "currency": "EUR", "createdAt": "2023-05-23T11:03:04.954Z", "type": "PARTIAL_REFUND" } ], "availableForRefund": 50, "isRefundableType": false, // will be true if you enabled refunds in montonio (and the user paid with a refundable method) "lineItems": [ { "name": "Hoverboard", "quantity": 1, "finalPrice": 100 } ], "billingAddress": { "firstName": "CustomerFirst", "lastName": "CustomerLast", "email": "test@montonio.com", "phoneNumber": null, "phoneCountry": null, "addressLine1": "Kai 1", "addressLine2": null, "locality": "Tallinn", "region": null, "country": "EE", "postalCode": "10111", "companyName": null, "companyLegalName": null, "companyRegCode": null, "companyVatNumber": null }, "shippingAddress": { "firstName": "CustomerFirstShipping", "lastName": "CustomerLastShipping", "email": "test@montonio.com", "phoneNumber": null, "phoneCountry": null, "addressLine1": "Kai 1", "addressLine2": null, "locality": "Tallinn", "region": null, "country": "EE", "postalCode": "10111", "companyName": null, "companyLegalName": null, "companyRegCode": null, "companyVatNumber": null }, "expiresAt": null, "createdAt": "2023-05-23T08:22:53.879Z", "storeName": "My Store Name", "businessName": "My Business Name", "paymentUrl": null // will be URL when order is PENDING } ``` The values for `paymentStatus` are described here - [Lifecycle of an Order](/api/stargate/overview#what-is-the-lifecycle-of-an-order), and the values for refunds' `status` are described here - [Lifecycle of a Refund](/api/stargate/overview#what-is-the-lifecycle-of-a-refund). ### Create Order #### Endpoint path ```http POST /orders ``` #### Request, response and authentication See [Create and validate an order -> Creating an order](/api/stargate/guides/orders#creating-an-order) for details. ### Create Refund #### Endpoint path ```http POST /refunds ``` #### Request, response and authentication See [Refund an Order](/api/stargate/guides/refunds) for details. ### Create Payment Link #### Endpoint path ```http POST /payment-links ``` #### Request, response and authentication See [Payment links](/api/stargate/guides/payment-links) for details. ### Create Session #### Endpoint path ```http POST /sessions ``` #### Authentication Refer to the code example in the [Embedded Cards in checkout](/api/stargate/guides/embedded-cards) guide or to the [Authentication section](/api/stargate/reference#authentication) above (follow instructions for POST endpoints). The generated token must be included in the `data` field of the request body. #### Request body The request body is a JSON object with a single field `data`, which contains the generated authentication token. #### Example request ```shell curl -X POST \ 'https://stargate.montonio.com/api/sessions' \ -H 'Content-Type: application/json' \ -d '{ "data": "eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.eyJhY2Nlc3NLZXkiOiIwMzA2M2I4Yi0wMjliLTQ5NTMtYTA0ZC02ZDNkNjRhZDdkNmUiLCJleHAiOjE3NTczNDM2NDl9.4mEIutn-C2kU4rEGS5zs1jlxjebvb0WzmsIFWAdbUIw" }' ``` #### Example response ```json { "uuid": "087a9fb5-7a85-4e1e-b3f7-2546faab9a97" } ``` --- # UI widgets URL: /api/stargate/widgets Here, you can find all the available widgets that can be used to develop your store's checkout. ## Montonio Checkout :::caution This checkout widget only displays the banks for the `paymentInitiation` method. **For other methods (cards, BLIK, financing, etc.) you should use your own UI elements.** ::: Montonio checkout is a JavaScript SDK that provides an easy way for e-commerce stores to display a selection of bank logos to their customers during the checkout process. The SDK generates the bank logos, along with a regions dropdown and two hidden input elements - one for the chosen provider and one for the chosen region. When the user selects a bank, the value of the hidden input element is set to the identifier of the chosen bank, which you can then pass to Montonio when creating an order. Below is an example of a checkout that utilises the SDK. **Please note that the SDK solely loads the bank selection component, not the entire page displayed below.** ### Complete example This is a complete example of how you could include the SDK in your stores checkout. ```html