diff --git a/_posts/2016-06-02-app-hooks.md b/_posts/2016-06-02-app-hooks.md index 5c7f41e..303ff75 100644 --- a/_posts/2016-06-02-app-hooks.md +++ b/_posts/2016-06-02-app-hooks.md @@ -11,7 +11,7 @@ order: 3 ## What is a hook? -Your app (extension) communicates with Mergado via [our API](https://mergado.docs.apiary.io/). In exchange, Mergado also needs to **actively communicate with your app**. +Your app (extension) communicates with Mergado via [our API](https://api-docs.mergado.com/?api=mergado-api). In exchange, Mergado also needs to **actively communicate with your app**. This is done via *web hooks*, which Mergado - at certain situations - calls upon your app's hook endpoints. To be specific, these *hooks* are *HTTP POST requests* with certain JSON (content type `application/json`) payload that specifies the hook's nature. diff --git a/_posts/2026-02-20-cross-platform-communication.md b/_posts/2026-02-20-cross-platform-communication.md index da597fc..9c447ef 100644 --- a/_posts/2026-02-20-cross-platform-communication.md +++ b/_posts/2026-02-20-cross-platform-communication.md @@ -56,6 +56,20 @@ Field | Description {: .message} **Important:** JWT tokens are **not refreshable**. Each proxied request receives its own fresh token valid for ~5 minutes. Once expired, the token cannot be used and a new request must be made. +### Verifying the JWT Token + +When your app receives a proxied request, it **must verify the JWT token** before processing the request: + +1. **Check expiration** — reject tokens where `expires_at` is in the past. +2. **Verify the signature** — validate that the token was issued by Mergado using the public key available at the [JWKS endpoint](https://api-docs.mergado.com/?api=mergado-api#/.well-known/jwks.json): + +``` +GET https://api.mergado.com/.well-known/jwks.json +``` + +{: .message} +**Important:** Never skip JWT verification. Without it, any third party could forge a proxied request to your app. Always verify both the token's expiration and its signature against Mergado's public key. + ### Using the JWT Token for Further API Calls The app can take the received JWT token and use it as a `Bearer` token in subsequent calls to the Mergado API: @@ -132,7 +146,7 @@ The endpoint always returns `HTTP 200` with a result for each requested check: } ``` -See the [API documentation](https://mergado.docs.apiary.io/) *(future link)* for full details. +See the [API documentation](https://api-docs.mergado.com/?api=mergado-api) *(future link)* for full details. #### When to call the access check endpoint diff --git a/_posts/2026-03-04-keychain.md b/_posts/2026-03-04-keychain.md new file mode 100644 index 0000000..b7df210 --- /dev/null +++ b/_posts/2026-03-04-keychain.md @@ -0,0 +1,68 @@ +--- +layout: page +title: "Keychain Proxy" +category: apps +date: 2026-03-04 00:00:00 +active_item: "" +order: 8 +--- + +Keychain is a Mergado service that stores and manages user credentials for third-party platforms (e.g. Heureka, Google Analytics, Shopify). It acts as a secure credential store — apps never handle credentials directly, but instead access external services through the Mergado proxy, which attaches the stored credentials automatically. +This document describes how to use the Keychain proxy in your app. + +## How It Works + +The app never handles user credentials directly. Instead, the user stores credentials for a third-party service in their Keychain, and the app communicates with that service through the Mergado proxy. + +The flow for every proxied request is: + +1. The user saves their credentials for a third-party service into their Keychain. +2. The app calls the proxy endpoint on Mergado. +3. Mergado attaches the stored credentials to the outgoing request. +4. The request is forwarded to the target service. +5. The response is returned to the app. + +``` +App Mergado Proxy Target Service + | | | + |-- proxy request --------->| | + | |-- attach credentials ---->| + | |<-- response --------------| + |<-- response --------------| | +``` + +## Using the Proxy in Your App + +The general implementation flow is: + +1. **Check whether the user has a connection** for the required service. Call the shop info endpoint (see [API documentation](https://api-docs.mergado.com/?api=mergado-api#/Eshops/get_shops__id__info_)) and inspect the returned connections. +2. **If no connection exists** — redirect the user to Keychain so they can create one. +3. **If a connection exists** — call the appropriate proxy endpoint for the service. The full list of available services and proxy endpoint patterns is in the [API documentation](https://api-docs.mergado.com/?api=mergado-api). + +The app never has access to the user's credentials at any point — the proxy layer handles authentication transparently. + +## Validating a Connection + +To check the current status of a specific Keychain connection, use the [validate endpoint](https://api-docs.mergado.com/?api=mergado-api#/Eshops/get_shops__id___connection__validate). + +The response contains: + +- `is_valid` — whether the connection is currently functional. Can be `null` when the validation itself cannot be completed (e.g. the external service is experiencing an outage or behaving unexpectedly). +- `errors` — an array of error objects with an `error` code and a human-readable `message` when `is_valid` is `false`. + +## Webhooks + +Mergado notifies your app via webhooks when the state of a Keychain connection changes — for example when a user creates or removes a connection. This allows your app to react without polling. + +The relevant hooks are `control.shop.keychain.link_created` and `control.shop.keychain.link_deleted`. Their payloads and full documentation are in the [Hooks documentation](https://mergado.github.io/docs/apps/app-hooks.html). + +**Note:** You can manage your app's hook URL via your app's *Storage* page in [Developers](https://developers.mergado.com). + +## Error Handling + +Apps should assume that an existing Keychain connection is functional. When a proxy call fails, the recommended approach is: + +1. **On proxy error** — call the validate endpoint to check the connection status. +2. **If the connection is invalid** — store the invalid state locally and stop making proxy calls. Wait for a `control.shop.keychain.link_created` webhook indicating the user has reconnected. +3. **Periodic re-check** — as a safety net (in case a webhook is lost or a temporary outage self-resolved), re-validate the connection periodically with a long interval (every few hours or once a day) for some time after the invalidation. +4. **Delay user notifications** — notify the user only after a re-validation attempt confirms the connection is still broken, to avoid false alarms caused by transient failures.