Connecting another system¶
Only in the Pro and Enterprise editions
An ERP system, a CRM, a form on another website is to enter subscribers. This guide takes the route through the REST interface — for a new integration it is the right choice.
You need somebody who can program for this. The interface is not a button but an interface.
1. Switch the module on¶
Newsletter → Configuration → Modules → REST interface → Module activated: Yes, then save.
Switching it on creates a key: 64 hexadecimal digits, shown on the module page. It is a key of its own — not the one for the SOAP interface.
Over http the contents go in clear text
The signature protects the key, not the mail addresses in the call. Set up
a certificate before you integrate. The module points this out in the
backend if your installation does not run over https.
2. Determine the address¶
The base address is shown on the module page. It has one of two forms:
with pretty permalinks https://your-domain.test/wp-json/wpng/v1/
without https://your-domain.test/?rest_route=/wpng/v1/
Pass your developers the address from the module page, not one you built yourself.
3. Hand over the key¶
Not by e-mail and not in a ticket system. Use whatever route your organisation has for credentials.
What the key can and cannot do
It permits exactly four things: read groups, create groups, create subscribers and assign subscribers to groups. It gives no access to newsletters, no access to the backend and none to existing subscribers.
That is the difference from the SOAP interface, whose key also signs the unsubscribe links in old mails.
4. The counterpart tests itself against /status¶
The first call your developers should make:
GET /wpng/v1/status
It creates nothing and changes nothing. If
{ "plugin": "wpNewsletterGermany", "version": "2.0.0", "zeit": 1789936431 }
comes back, the address, key and signature are right — and the integration can get going without leaving a test subscriber in your list.
zeit is your installation's time
The time window for a call is 15 minutes. If the counterpart's clock
runs differently, every call fails with wpng_rest_zeit_abgelaufen — and
/status says by how much.
5. Fetch the groups¶
GET /wpng/v1/groups
[ { "id": 1, "name": "Prospects" }, { "id": 2, "name": "Customer newsletter" } ]
Have the counterpart fetch the numbers rather than hard-coding them. Otherwise renaming or creating a group breaks the integration.
6. Create a subscriber¶
POST /wpng/v1/subscribers
{ "email": "new@example.test", "vname": "Anke", "name": "Brandt", "sendOptIn": 1 }
Settle status and sendOptIn before the first call runs
| Choice | Consequence |
|---|---|
"sendOptIn": 1 |
The confirmation mail goes out from here. The subscriber only becomes active on the click |
"status": 2 |
The subscriber is active immediately, without confirmation |
The first route is almost always the right one: consent is then provable here.
The second assumes that the third-party system obtained the consent itself and documented it. Ask where that proof lives before you allow it — the plugin writes no consent record for subscribers created through the interface.
If the system already knows the address, 409 comes back with the ID of the
existing subscriber. That is not an error but enough to carry on with.
7. Assign to a group¶
POST /wpng/v1/groups/2/subscribers
{ "abo": [ 70, 71 ] }
{ "group_id": 2, "zugeordnet": [ 70 ], "unbekannt": [ 71 ] }
Assignment is additive — existing groups stay. A subscriber that does not exist does not make the call fail; the answer names both lists.
The signature¶
Every call carries two headers:
X-WPNG-Timestamp |
Unix time |
X-WPNG-Signature |
HMAC-SHA256 over method, route, query part, time and body |
The complete example is under REST interface.
The three most common mistakes when integrating:
| Error | Cause |
|---|---|
wpng_rest_zeit_abgelaufen |
The clocks have drifted apart. Check NTP on both sides |
wpng_rest_signatur_falsch |
Usually the body: it has to be signed character for character as it goes over the wire. Calling json_encode() again after signing produces a different body |
| The empty line is missing | Without query parameters the third line of the signature is empty — the line break stays all the same |
What else you should settle¶
Who gets to see subscriber data? The third-party system is thereby a recipient in the sense of your privacy policy. Only you know who that is — and it belongs in there.
What happens with a sync in the other direction? The interface cannot read who has unsubscribed. If your third-party system needs to know that, you need another route for it — the CSV export, for instance.
Who renews the key when it becomes necessary? Generate a new key rejects every counterpart still using the old one. Agree it beforehand.
And if it has to be SOAP¶
If your third-party system only speaks SOAP, that still works — see SOAP interface.
Two differences your developers have to know:
addToGroupreplaces the subscriber's groups instead of adding to them.getGroupsanswers undermessage, not underdata.
And: it needs the PHP extension soap on your server.