Frequently asked questions
Is there a PHP or Laravel package for the MKG ERP API?
Yes, darvis/mkg-client. It is a PHP client that reads debtors, articles, sales orders, addresses, relations, contact persons and users from the REST API of MKG Software. It handles the login and the session cookie and returns typed rows. It works in plain PHP and registers itself in Laravel. Install it with composer require darvis/mkg-client.
Is darvis/mkg-client an official MKG package, and what does it cost?
No, it is an independent open-source package, maintained by ARVID.NL and not affiliated with MKG Software. It is free under the MIT license. The MKG side is not free; you need an MKG installation with the API set up, an MKG Exchange license and an API key.
Which PHP and Laravel versions does darvis/mkg-client need?
PHP 8.2 or higher. The Laravel integration works on Laravel 11, 12 and 13; without Laravel the client runs in plain PHP with Guzzle 7. On Laravel 11 the services must be bound in a service provider, otherwise the timeout and TLS settings are not applied; the Troubleshooting page has the snippet.
How do I connect a Laravel application to MKG?
Run composer require darvis/mkg-client, set MKG_HOST, MKG_CUSTOMER (the API key), MKG_USERNAME and MKG_PASSWORD in .env, and call a service, for example app(DebtorsService::class)->findDebtorRowsByDebtorNumber(10001). The client builds the URLs from the host, logs in at the first request and reuses the session.
What is the base URL of the MKG REST API, and how does the login work?
The base is https://{host}/mkg/web/v3/MKG/Documents; a training environment uses mkgoefenclient instead of mkg. MKG runs on Tomcat with form authentication: POST j_username and j_password to https://{host}/mkg/static/auth/j_spring_security_check with the API key in the X-CustomerID header. The response sets a JSESSIONID cookie that goes with every following request, together with X-CustomerID. There is no OAuth and there are no bearer tokens.
Why does the MKG API return 403 Forbidden?
Because the request never reached the REST API. A 403 with an HTML body is Tomcat’s own error page and means the URL path is wrong, for example the retired /mkg/rest/v1 or /mkg/rest/v3. It is not a permission problem and not an expired session, so logging in again does not help; correct the base URL.
Why does the MKG API return 401 Not authenticated?
The session expired or the JSESSIONID is unknown. MKG answers with JSON: {"status_code":401,"status_txt":"Not authenticated"}. Log in again and repeat the request. This package does that by itself, once per request.
Why do I only get 100 rows back from MKG, and how do I get more?
NumRows defaults to 100 when you leave it out, and 1000 is a hard ceiling: NumRows=2000 returns 1000 rows without an error. Page with SkipRows as the offset together with NumRows, and add Sort so the order is the same on every page. In this package those are the numRows, skipRows and sort arguments of the order list methods.
How do I test code that uses darvis/mkg-client without calling MKG?
Give the service a Guzzle client with a MockHandler and bind it in the container. Http::fake() does not work, because the package uses Guzzle directly and not Laravel’s HTTP client. Put JSESSIONID=test in mkg/cookie.txt on a faked disk so no login response is needed.
Is it safe to pass user input to darvis/mkg-client?
The finders quote and escape their value and the primary key methods URL-encode theirs, so a value cannot change the filter or the URL. A filter string you write yourself is sent as it is, so validate user input before you put it in one. The session cookie is stored on Laravel’s default filesystem disk, which must not be public.