Skip to content

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:

  • addToGroup replaces the subscriber's groups instead of adding to them.
  • getGroups answers under message, not under data.

And: it needs the PHP extension soap on your server.