Skip to main content
Version: 2.0.0

Developer API

The Kros plugin exposes services, an invoice provider, a webhook receiver, an order-edit UI component, and MCP tools for integration with yStore's invoicing system and external/automation clients.

Services

Access services via the plugin instance:

use Yui\Kros\Plugin;

$kros = Plugin::getInstance();
$api = $kros->getApi();
$invoices = $kros->getInvoices();
$webhooks = $kros->getWebhooks();
$dashboard = $kros->getDashboard();
$license = $kros->getLicense();

ApiService

Builds the authenticated Guzzle client used for every KROS OpenAPI call (getConnection()), sending the saved API Token as a Bearer header against API Base URL. request(string $method, string $uri, array $options = []) wraps the call, adds Accept/Content-Type headers, and disables Guzzle's http_errors so 4xx/5xx responses are still returned instead of throwing. Every response is passed through validateMeta(), which reads the x-rate-limit-limit / x-rate-limit-remaining / x-rate-limit-reset response headers (if present) and persists them onto the plugin's own settings (Rate Limit, Remaining, Reset in the CP sidebar).

InvoiceService

Creates, updates, downloads, and lists KROS invoices from order data.

  • createInvoice(int $orderId, ?string $orderStatus, bool $manualCreate = false) -- creates an invoice for an order. When $manualCreate is false, it only proceeds if $orderStatus is one of the configured Generate invoice when statuses. Refuses to create a duplicate invoice for an order that already has one, refuses a zero-total order unless Zero Total Orders is enabled, and refuses an order whose increment ID is longer than 10 characters (KROS variable-symbol limit). Returns true on success, false on an unexpected failure, or an array of human-readable error messages.
  • createInvoiceFromData(array $invoiceData, bool $manualCreate = false) -- the invoice-provider entry point; builds the invoice from a normalized $invoiceData array (with order_id/order_status under meta) instead of loading the order directly. Used by KrosInvoiceProvider::createInvoice().
  • updateInvoice(int $orderId, ?string $orderStatus, bool $manualUpdate = false) -- re-sends the invoice data for an order that already has a recorded invoice.
  • downloadInvoice(int $orderId) -- returns the invoice PDF as a Craft Asset, fetching it from KROS using the configured Invoice PDF Report ID if it hasn't been downloaded yet. Returns false on failure.
  • deleteInvoice(int $id) -- deletes a locally recorded invoice.
  • syncRemoteInvoiceById(int $invoiceId) / deleteRemoteInvoiceById(int $invoiceId) -- used by the webhook receiver to keep the locally cached remote-invoice table (when Store Remote Invoices in Database is enabled) in sync with KROS-side changes.
  • getInvoicesByOrderId(int $orderId) -- lists every invoice recorded for an order.
  • getInvoiceByIncrementId(string $incrementId) -- looks up an invoice by the order's increment ID.
  • getInvoices(int $page = 1, int $perPage = 10, ?string $searchTerm = null) -- paginated/searchable listing backing the Kros → Invoices CP page and its kros/invoices/get-list endpoint.

Every invoice/client/item detail sent to KROS is assembled from the order (address, line items, shipping, payment) and the plugin's settings (VAT payer type, tax class, invoice language, opening/closing text, due date, and whether shipping/payment are added as line items).

WebhookService

Manages the KROS-side webhook registration and validates incoming webhook signatures.

  • getResolvedWebhookUrl() -- returns the configured Webhook URL, or falls back to the plugin's own kros/webhooks/receive action URL.
  • syncWebhook() -- implements the create/update/delete logic for the KROS-side webhook (deletes it if Enable Webhooks is off and one was previously registered; otherwise creates or updates it with the configured URL, events, and secret, storing the returned webhook ID back onto the plugin settings). As of v1.3.0 this method is not called anywhere -- saving the settings form does not invoke it, so the webhook must currently be registered manually on the KROS side.
  • validateSignature(string $payload, ?string $signature) -- computes an HMAC-SHA256 signature of the raw request body using Webhook Secret and compares it (constant-time) against the incoming Signature Header value (sha256= prefix stripped if present). Returns false -- rejecting the request -- whenever the secret or the incoming signature is missing, so webhooks fail closed by default.

DashboardService

Extends the shared yui\craftcore\services\CoreDashboardService to build the Kros → Dashboard modules: Total invoices, In this period, Synced to KROS, and Pending sync KPI tiles, and a Recent invoices table (date, order, invoice ID, external ID; latest 12).

LicenseService

Backs the Kros → License CP page (shared yui/craft-core license activation/status UI).

Invoice provider

Yui\Kros\providers\KrosInvoiceProvider registers itself with handle kros on yui\craft\services\sales\InvoiceService::EVENT_REGISTER_INVOICE_PROVIDERS, so it appears alongside any other invoice provider yStore has registered.

public function isEnabled(): bool
{
return (bool)(Plugin::getInstance()?->getSettings()?->enabled ?? false);
}

The provider is enabled purely based on the Enabled settings toggle. createInvoice() delegates to InvoiceService::createInvoiceFromData(), and getAttachments() returns the invoices already recorded for the order (via $invoiceData['meta']['order_id']) using InvoiceService::getInvoicesByOrderId().

Webhooks

WebhooksController::actionReceive() (route: kros/webhooks/receive, anonymous access, CSRF validation disabled since KROS posts without a Craft CSRF token) is the single entry point for KROS-originated events:

  1. If the plugin is disabled, the request is acknowledged ({"ok": true}) without further processing.
  2. The raw request body is checked against WebhookService::validateSignature() using the header named by Signature Header (default X-Kros-Signature). A missing/invalid signature returns 401 and logs a warning with the request IP and header name -- it does not process the payload.
  3. The JSON payload's event type (event/type/eventType) and invoice ID (invoiceId/id/invoice.id) are extracted. If Store Remote Invoices in Database is enabled and an invoice ID is present, a deleted-type event calls deleteRemoteInvoiceById(), any other event calls syncRemoteInvoiceById().

Configure the webhook via Settings → Kros → Webhooks (see Settings); a Webhook Secret is mandatory for the endpoint to accept any request. As of v1.3.0, syncWebhook() is never invoked automatically, so the webhook itself must be registered manually in KROS Fakturácia, pointed at kros/webhooks/receive (or the configured Webhook URL) -- saving the settings form only stores the local configuration used to validate and process the events KROS sends.

Order-edit component

When Show Kros Button is on, the plugin hooks into the order-edit-extra-actions template hook and renders a Kros menu button on the order edit page (kros/components/order/edit/manage-invoice.twig). The menu offers:

  • Create Invoice -- shown when the order has no recorded invoice yet.
  • Update Invoice -- shown when the order already has one.
  • Download Invoice -- always available.

These map to InvoiceController::actionCreate(), actionUpdate(), and actionDownload().

MCP Tools

When the yui/craft-mcp plugin is installed, Kros registers three MCP tools on yui\mcp\Plugin::EVENT_REGISTER_TOOLS, all extending the shared AbstractKrosTool base, which accepts an order identifier (order_id and/or increment_id).

kros_get_invoices

Lists all Kros invoices for a given order.

Output:

{
"order_id": 123,
"count": 1,
"invoices": ["..."]
}

kros_create_invoice

Manually creates a Kros invoice for an order, bypassing the order-status trigger and forcing creation. Fails if an invoice already exists for the order. Requires WRITE permission.

kros_download_invoice

Downloads (or returns the already-cached asset for) the Kros invoice PDF for an order. Returns the asset URL and filename, or success: false with an error message if the PDF could not be fetched.

{
"success": true,
"order_id": 123,
"url": "https://.../invoice.pdf",
"filename": "invoice.pdf"
}

Requires WRITE permission.

Settings model

Yui\Kros\models\Settings (extends yui\craftcore\models\BasePluginSettingsModel) holds every field documented in Settings. Validation: apiBaseUrl, apiToken, dueDateDays, createInvoiceOnOrderStatus, and invoiceReportId are required whenever the plugin is enabled (Settings::rules()). apiToken, apiBaseUrl, and numberingSequence are site-overridable (siteOverridableAttributes()), so a multi-site store can use different KROS credentials/sequences per site.

CP Routes

RoutePurpose
kros / kros/dashboardDashboard
kros/invoices, kros/invoices/get-list, kros/invoices/deleteInvoice list, AJAX listing, delete
kros/invoice/create/<orderId>, /update/<orderId>, /download/<orderId>Manual invoice actions from the order edit page
kros/settingsSettings
kros/webhooks/receiveWebhook receiver (anonymous, KROS-originated)
kros/licenseLicense activation/status
kros/license/redeem, /revoke, /activate, /delete, /copy-tokenLicense actions

Permissions

The plugin registers three CP user permissions under the Kros heading: yui:kros:create (Create invoice), yui:kros:update (Update invoice), and yui:kros:download (Download invoice).

Compatibility

  • Craft CMS 5+
  • Craft Commerce and yui/craft-core ^1
  • KROS Economy API (https://api-economy.kros.sk) -- see KROS API docs and invoice reference
  • Optional: yui/craft-mcp, for the MCP tools described above