Integration tests and a browser-based API playground for the Maileon PHP API client (source on GitHub).
Requires PHP 7.4+ and Composer on the host.
git clone https://github.com/xqueue/maileon-php-api-client-examples.git
cd maileon-php-api-client-examples
composer install
php -S localhost:8000 -t ui/Open http://localhost:8000.
No PHP or Composer required on the host — only Docker.
git clone https://github.com/xqueue/maileon-php-api-client-examples.git
cd maileon-php-api-client-examples
docker compose up --buildOpen http://localhost:8080.
The Dockerfile uses the official php:8.2-cli image, installs Composer inside the container, runs composer install, and starts the PHP built-in server on port 8080.
After starting with either method, create a vault with a password and enter your Maileon API key in the Configuration section. All configuration is stored encrypted in a browser cookie — nothing is written to disk.
For a production or shared server, point your web server's document root at the ui/ directory instead of using the built-in PHP server.
- PHP 7.4 or 8.x
- Composer
- A Maileon account with an API key
composer install
cp conf/config.php.default conf/config.php
# Edit conf/config.php with your API key and test data IDs.Alternatively, set environment variables (they take precedence over conf/config.php):
cp .env.example .env
# Edit .envA single-file browser-based API explorer. Select tests, override parameters per run, inspect requests and responses, and view the raw curl debug log — all without touching the CLI.
It will also provide sample code in PHP, e.g.:
Native:
php -S localhost:8000 -t ui/
# Open http://localhost:8000Docker (no local PHP/Composer required):
docker compose up --build
# Open http://localhost:8080Or point any web server's document root at the ui/ directory.
All configuration (API key, base URI, test data) is stored in an AES-256-CBC encrypted browser cookie. The key is derived from your password via PBKDF2-SHA256 (100,000 iterations). Your password is never stored anywhere.
On first visit, choose the New vault tab and set a password:
After unlocking, the sidebar lists all 13 API service sections. Without a configured API key, a banner links directly to Configuration:
Enter your API key, base URI, and test data IDs. Enable debug mode to show the curl verbose log per call. All values are AES-256 encrypted on save:
Select one or more tests, optionally filter with the search box, then click Run selected. When tests require specific values (email address, target group name, etc.) a Parameters panel appears so you can override them for that run without changing the saved config.
Results display:
- HTTP method badge (color-coded GET / POST / PUT / DELETE)
- Full request URL
- Elapsed time in milliseconds
- HTTP status badge (color-coded by class)
- Collapsed Request headers section
- Response tabs: Preview (deserialized) · Raw (XML/JSON body) · Headers · Debug (curl verbose log)
The Debug tab shows the full curl session log with the Authorization header redacted. Useful for verifying exact request headers, SSL handshake, and redirect chains:
Every test entry has a </> button next to its label. Click it to open a modal with minimal, copy-pasteable PHP code for that specific API call.
- Parameter values entered in the Parameters panel are pre-filled into the snippet.
- The snippet includes all required
usestatements and a standard result-check block. - Click Copy to copy the code to the clipboard, or close the modal by clicking ✕ or anywhere outside it.
This makes it straightforward to transfer a tested call directly into your own project without having to look up the method signature.
Integration tests make real API calls. They create, modify, and delete data in your Maileon account.
# Enable and run all integration tests
MAILEON_RUN_INTEGRATION=1 MAILEON_API_KEY=your-key composer test
# Run a single service
MAILEON_RUN_INTEGRATION=1 MAILEON_API_KEY=your-key composer test:contacts
MAILEON_RUN_INTEGRATION=1 MAILEON_API_KEY=your-key composer test:dataextensions
MAILEON_RUN_INTEGRATION=1 MAILEON_API_KEY=your-key composer test:transactionsWithout MAILEON_RUN_INTEGRATION=1, all tests are marked as skipped — safe to run in CI.
| Service | Tests |
|---|---|
| PingService | GET, PUT, POST, DELETE |
| ContactsService | CRUD, custom fields, sync, unsubscribe, preferences |
| ContactFiltersService | count, list, get, create, update, refresh, delete |
| TargetGroupsService | count, list, get, create, delete |
| MailingsService | create/delete, HTML, subject, sender, reply-to, preview, tags, locale, custom properties, QoS, archive URL, report URL, domain, copy, contact filter restrictions |
| MediaService | list CMS1 templates, list CMS2 templates |
| ReportsService | unsubscribers, subscribers, recipients, opens, clicks, bounces, blocks, conversions |
| TransactionsService | type CRUD (simple + complex), create transactions, recent, get/delete by ID |
| BlacklistsService | list, get, add entries |
| MailingBlacklistsService | CRUD, add entries, get entries |
| AccountService | info, placeholder CRUD, mailing domains |
| WebhooksService | list, get, create, update, delete |
| DataExtensionsService | list (paginated), get data types, create, get, update (description + add fields), delete, synchronize records (UPSERT, INSERT_IGNORE_DUPLICATES), get records (filtered, sorted), delete all records, empty payload guard |
Some tests require pre-existing objects in your account:
| Env var | Required for |
|---|---|
MAILEON_TEST_MAILING_ID |
All Reports tests |
MAILEON_TEST_CF_ID |
ContactFilters — get by config ID |
MAILEON_TEST_BLACKLIST_ID |
Blacklists — get, add entries |
MAILEON_TEST_DE_ID |
All DataExtensions tests |
MAILEON_TEST_TX_TYPE_ID |
Transactions — get type from config |
MAILEON_TEST_TX_ID |
Transactions — get/delete by ID |
MAILEON_TEST_WEBHOOK_ID |
Webhooks — get from config |
Tests that require these IDs are automatically skipped when the IDs are not set.
To expose a new API method in the playground / test UI, touch five places:
Add a test method to the relevant *Test.php class in tests/. Follow the existing pattern: call the service, assert $result->isSuccess(), clean up in tearDownAfterClass().
Add an elseif ($key === 'your_test_key') block inside the main dispatch loop. Use _res() for a real call, _skp() to skip with a reason. Parse any user-supplied params from the $p array:
} elseif ($key === 'your_test_key') {
$id = (int)($p['some_id'] ?? 0);
$r = _res('Label', (new SomeService($cfg))->someMethod($id));For dates use _parse_date_ms(), CSV integers _parse_csv_ints(), CSV strings _parse_csv_strings(), booleans _parse_bool_str().
VAULT_PARAMS (PHP array, ~line 967): add a default value for each new param key so the params panel has an initial pre-fill.
PARAM_LABELS (JS object, ~line 1022): add a human-readable label for each param key. These appear above the input fields.
TEST_PARAMS (JS object, ~line 1057): add your test key and declare which params are required (r) vs optional (o):
your_test_key: { r: ['required_param'], o: ['optional_param'] },ORDER (array inside updateParamsPanel(), ~line 1300): append new param keys in the order they should appear in the params panel. A param not in ORDER will never appear in the panel even if listed in TEST_PARAMS.
Add an entry that returns a _tpl([NS.SVC], call) with a copy-pasteable PHP snippet (~line 1520). Use _phpVal() for scalar params, _rDate() / _rCsvI() / _rCsvS() / _rBool() for report-style date/list/bool params:
your_test_key: p => _tpl([NS.SOME_SVC], `$svc = new SomeService($config);\n$resp = $svc->someMethod(${_phpVal(p.some_id)});`),If there is no useful snippet, omit the entry — the </> button simply won't appear for that test.
Find the $tests PHP array in the section that builds the sidebar (search for 'ping_get'). Add your entry as ['your_test_key', 'Display label', 'read'|'write', 'section-slug']. The section slug must match one of the existing sidebar sections.
Tests create and clean up their own data. Cleanup runs in tearDownAfterClass() even if tests fail.
The following operations affect real account data — review before running:
ContactsService: creates and deletes test contactsTransactionsService: creates transaction types and sends transactionsMailingsService: creates and deletes mailingsBlacklistsService: adds entries to a blacklist (requiresMAILEON_TEST_BLACKLIST_ID)DataExtensionsService: creates and deletes a temporary data extension for CRUD tests; also writes records to an existing extension (requiresMAILEON_TEST_DE_ID)





