Docs menu: Connect a store
Connect a store
Guides
A store never holds a vendor’s secret key. Its owner approves it on a Tallio page, and the store’s server exchanges a one-time code for its restricted keys, bound to one merchant.
On this page
Important
Keep the store’s keys sealed on its server: never in a URL, a page or the browser. A restricted key (rk_live_…, rk_test_…) acts for its own merchant only, and only through the operations listed below.
The grant #
Connect to Tallio is an OAuth 2.0 authorization code grant with PKCE (S256). The code travels in the browser; the verifier never leaves the store’s server, so a code alone is useless.
- Ask. The store keeps a random
stateand acode_verifier(43 to 128 characters), and sends its admin’s browser to Tallio’s hosted page with the challenge.redirect_urimust be exactly the store’s callback under its URL, nothing else. - Consent. The admin signs in to Tallio, or signs up, and an owner of the team approves the store, confirming with a second factor or a fresh sign-in. On a first connect they also type the business’s tax ids, and Tallio creates its merchant.
- Return. The browser comes back to
redirect_uriwithcodeand the samestate, or witherror=access_deniedwhen the admin cancels. The code lives 10 minutes. - Exchange. The store’s server calls POST /store_grants/token with the code, the verifier and the same
redirect_uri, naming itself inTallio-Store-Url. The answer, given once, holds the merchant, the team, the two keys and the secrets of the store’s webhook endpoints.
Send the admin’s browser toGET /dashboard/connect-store
?platform=woocommerce
&store_url=https://shop.example
&redirect_uri=https%3A%2F%2Fshop.example%2Fwp-admin%2Fadmin.php%3Fpage%3Dtallio-connect
&state=…
&code_challenge=…
&code_challenge_method=S256
&locale=elExchange the code, from the store’s servercurl "$TALLIO_API_URL/v1/store_grants/token" \
-H "Tallio-Store-Url: https://shop.example" \
-H "Content-Type: application/json" \
-d '{"grant_type":"authorization_code","code":"…","code_verifier":"…","redirect_uri":"https://shop.example/wp-admin/admin.php?page=tallio-connect","store_environment":"production"}'Every refused exchange is the same 400 invalid_grant, whatever the cause. Never retry a successful exchange: exchanging a spent code again with its verifier revokes the keys it made, since a replay means the code leaked. After a lost answer, connect again.
The hosted page’s language #
Pass the admin’s language in locale (el, fr_FR, en_US): sign-in and the consent page follow it when Tallio speaks it, for that session only. An unknown or missing value never refuses the request.
Live and test keys #
The exchange always answers a test key, and a live key only for a production store. Send store_environment (production, staging, development, local): anything but production gets a test key only, as does a development host (localhost, .test, a private address, a public tunnel). A test key issues through the merchant’s test connection, or Tallio’s sandbox when there is none.
The store’s URL #
A store’s keys are bound to its URL. Send it in Tallio-Store-Url on every call: another value, or none, is 409 store_url_mismatch. It keeps a staging copy of the store from issuing live with copied settings; it is not a secret. When the store really moved, its admin confirms the move and the store sends its new URL to PUT /store_binding; while the store has a live key, only that key may move it.
What a store key can call #
A store key reaches only the operations in the table below, and only for its own merchant: another merchant’s ids answer 404, as if they did not exist. Any other operation is 403 restricted_key: a store key cannot create merchants, list events, manage webhook endpoints or keys, or reach the MCP server.
When the store disconnects or the plugin is removed, the store gives up each key with DELETE /api_keys/current. A team owner can also revoke the store’s keys from the dashboard; a new connection replaces the old keys.
Store key operations #
Generated from the API’s operation registry, the list the API checks every store key against.
| Operation | Call |
|---|---|
| Retrieve a document | GET /documents/{id} |
| Download a document's PDF | GET /documents/{id}/pdf |
| Retrieve a merchant | GET /merchants/{id} |
| Erase a customer's data | POST /erasures |
| Send a shop order | POST /store_orders |
| Retrieve a store order | GET /store_orders/{id} |
| List store orders | GET /store_orders |
| Retry a store order | POST /store_orders/{id}/retry |
| Mark a store order handled | POST /store_orders/{id}/mark_handled |
| Review a waiting invoice | POST /store_orders/{id}/invoice_review |
| Confirm a waiting invoice | POST /store_orders/{id}/confirm_invoice |
| Correct a store order's document | POST /store_orders/{id}/correct |
| Cancel a store order's document | POST /store_orders/{id}/cancel |
| Save a buyer's invoice request | PUT /store_orders/{id}/invoice_request |
| Send a refund of a store order | POST /store_orders/{id}/refunds |
| Mark a store refund handled | POST /store_orders/{id}/refunds/{refundId}/mark_handled |
| Retrieve a merchant's store settings | GET /merchants/{id}/store_settings |
| Update a merchant's store settings | PATCH /merchants/{id}/store_settings |
| Retrieve the store plan's usage | GET /store_usage |
| List a merchant's connections | GET /merchants/{id}/connections |
| Retrieve a connection | GET /connections/{id} |
| Create a hosted connect link | POST /merchants/{id}/connect_sessions |
| Look up a VAT number | GET /tax_ids/lookup |
| Revoke the key making this request | DELETE /api_keys/current |
| Confirm that the store moved to a new URL | PUT /store_binding |