Woosa Payments: A Step-by-Step Integration Guide
Learn how to process payments with Adyen via Woosa Payments
Contents
- Who this guide is for
- The big picture (read this first)
- Before you start: what you need
- Part 1: Build the endpoints Woosa will call back (non-WooCommerce only)
- Part 2: Register your shop
- Part 3: How to sign every request (the signature)
- Part 4: Connect your merchant account
- Part 5: Set up a legal entity and a store, then onboard
- Part 6: Choose which payment methods are active
- Part 7: Take a payment (the core loop)
- Part 8: After the payment (capture, refund, cancel, status)
- Part 9: Housekeeping
- Part 10: Go live
- Quick reference: all endpoints
- Common mistakes and how to avoid them
- Glossary
Who this guide is for
You are building, or helping build, an online shop that is not WooCommerce (a custom stack, a headless frontend, a different framework etc.), and you want to accept payments through Woosa Payments.
If your shop runs on WooCommerce, you do not need any of this. There is a ready-made plugin. Install it, configure it, done. This guide only matters for shops that are not WooCommerce.
You do not need to be a payments expert to follow this. Wherever a technical term shows up, it is explained in plain words the first time, and there is a glossary at the end. You will need someone who can write a bit of backend code to actually wire it up, but this guide is meant to make the whole journey understandable before a single line is written.
The big picture (read this first)
Woosa Payments sits between your shop and Adyen (the actual payment processor). You never talk to Adyen directly. You talk to a Woosa server called the Midlayer, and the Midlayer talks to Adyen for you.
There are two base addresses for the Midlayer:
| Environment | Base URL |
|---|---|
| Development (for testing) | https://midlayer-dev.woosa.nl |
| Production (real money) | https://midlayer.woosa.nl |
Here is the part that trips people up, so let us be clear about it up front. The connection works in two directions:
- You call Woosa. Most of the time your shop sends requests to the Midlayer: "create a payment", "refund this", "list my stores". This is the normal, outbound direction.
- Woosa calls you. During setup, the Midlayer calls back to your shop to check your credentials and to hand you a secret key. Your shop has to expose a few small endpoints that the Midlayer can reach.
That second direction is the whole reason a non-WooCommerce integration takes a little extra work. A WooCommerce shop already exposes these endpoints out of the box. Yours does not yet, so you should build them first. How to do that is described in Part 1 below.
A useful way to picture the full journey:
[ PREP ] Build 3 small endpoints on your shop that Woosa can call back to.
|
[ REGISTER ] Tell Woosa your shop exists. Woosa calls you back and gives you a secret key.
|
[ SIGN ] From now on, every request you send should be "signed" with that secret key.
|
[ CONNECT ] Create or link your existing Woosa Payments UI account (email + verification code).
|
[ SET UP ] Pick your legal entity, create a store, complete onboarding (ID checks).
|
[ CONFIGURE ] Choose which payment methods (iDEAL, cards, Klarna, etc.) are active.
|
[ TEST ] On the dev environment, run real test payments end-to-end.
|
[ GO LIVE ] Onboard the real legal entity in production and switch the base URL.
|
[ TAKE MONEY ] Create payments, handle any extra shopper steps, capture, refund.
We will walk through each block in order.
Before you start: what you need
- A shop with a public URL (for example
https://myshop.example.com). - The ability to add API endpoints to that shop's backend (Part 1 needs this).
- API key and secret pair. These are two random strings. They act like a username and password that Woosa uses to call your shop back. If your platform does not generate these for you, you make up two strong random strings and store them. You will hand them to Woosa during registration, and Woosa will use them to authenticate its callbacks to you.
- An email address for Woosa Payments UI account.
Part 1: Build the endpoints Woosa will call back (non-WooCommerce only)
You need to expose three endpoints on your own shop. Build these before you try to register, because registration will immediately call two of them.
The paths use the WooCommerce naming on purpose. The Woosa server expects these exact paths and contracts, because it treats every shop as if it were WooCommerce.
1a. “Give me your settings” endpoint
GET /wp-json/wc/v3/settings/general
What it is for: before your shop is registered, Woosa calls this to validate that the key and secret you gave are real.
Rules:
- Protect it with HTTP Basic Auth. Basic Auth is the simplest form of login for an API: the caller sends your key
as the username and your secret as the password. Your endpoint checks they match the pair you registered with. If
they do not match, reply with
401 Unauthorized. - On success, return a JSON list of setting objects. At minimum, include one entry whose
idiswoosa_secret. - The very first time, you do not have a secret yet, so return an empty string for its value.
Example response (first time, no secret yet):
[
{
"id": "woosa_secret",
"value": ""
}
]
1b. “Save a setting” endpoint
POST /wp-json/wc/v3/settings/general/batch
What it is for: once Woosa has confirmed your credentials and registered your shop, it generates a secret key for your shop and pushes it to
you through this endpoint. You store it. From that moment on, this woosa_secret is
what you use to sign every request (Part 3).
Rules:
- Protect it with the same HTTP Basic Auth as above.
- Accept a body with an
updatearray. Each item has anidand avalue. - Save each setting, then return the updated objects in the same shape as the GET endpoint above.
Example request Woosa sends you:
{
"update": [
{
"id": "woosa_secret",
"value": "8caa59a1c330f23d55de3bdd339a1c330f23d55"
}
]
}
Store the secret key somewhere safe and permanent (encryption is recommended). This is the single most important secret in the whole integration. If you lose it, you cannot sign requests, and nothing works.
1c. “Onboarding return” endpoint
GET /wp-json/woosa-payments/onboarding-redirect
What it is for: later, the merchant gets sent to an Adyen page to prove their identity (see Part 5). When they finish, they get bounced back to this URL. Its only job is to redirect the merchant to the right page in your own shop's admin (for example, back to a "Payments settings" screen).
Rules:
- No authentication needed.
- Respond with a
302redirect to wherever you want the merchant to land.
That is the full extent of the extra work. Three small endpoints. Two of them are essentially a tiny key-value store guarded by Basic Auth, and the third is a redirect. Build these, then move on.
Part 2: Register your shop
Now you tell Woosa that your shop exists.
POST /woocommerce/shops
- This is the one and only request that should not be signed. You have no secret key yet, so there is nothing to sign with.
Body:
{
"url": "https://myshop.example.com/",
"key": "ck_781d7a45573443cba7e263901c0c5da511e98949d1",
"secret": "cs_029425b4341cce8caa5de3bdd339a1c330f23d55",
"version": "wc/v3",
"auth": "basic"
}
What happens behind the scenes (this is the "handshake"):
- Woosa receives your registration.
- Woosa calls your GET settings endpoint from Part 1a, using the key and secret you just sent, to confirm they work.
- If that succeeds, Woosa generates your
woosa_secretand pushes it to your POST batch endpoint from Part 1b. - Your shop stores the secret.
A successful registration returns 204 No Content (an empty success). If you get a
401, it usually means Woosa could not authenticate against your callback endpoints,
so double-check Part 1. If you get a 400, something in the body is wrong.
After this step you hold a woosa_secret. Everything from here on is signed with
it.
Part 3: How to sign every request (the signature)
From now on, almost every request must carry a signature. Think of a signature as a tamper-proof wax seal. It proves two things to Woosa: that the request really came from you, and that nobody changed it in transit. It is recomputed fresh for every single request.
You will send three headers on signed requests:
| Header | Value |
|---|---|
| x-woosa-domain | your shop domain, e.g. myshop.example.com |
| x-woosa-signature | the signature you compute below |
| x-woosa-signature-type | plugin (this is the documented default) |
How the signature is built
You put three pieces of information into a small package, scramble it with your secret using a standard one-way function (HMAC-SHA256), and stick a timestamp on the front. The three pieces are:
- uri: the request path of Woosa API endpoint you are going to call plus any query string, always starting with
/. Example:/woocommerce/adyen/stores/ST32.../payments. - body: the exact raw content of the request body you are sending. For GET requests, which have no body,
use an empty string
"". - time: the current time as a Unix timestamp (seconds since 1970).
Then:
- Build a JSON object
{ "uri": ..., "body": ..., "time": ... }. - Turn it into HMAC-SHA256 using your
woosa_secretas the key, and Base64-encode the result. That is yourdataSignature. - The final header value is
time+ a dot +dataSignature.
The end result looks like this:
1636117273.MNw1Rd5O0evUmwXy85j0ca2bg8SDg/Xm4WfA3LdI5gg=
PHP example
$data = [
'uri' => $uri, // e.g. "/woocommerce/adyen/stores" (path + query, starts with /)
'body' => $body, // the exact JSON string you send; "" for GET
'time' => time(),
];
$dataSignature = base64_encode(hash_hmac('sha256', json_encode($data), $secret, true)); // $secret = your woosa_secret
$finalSignature = sprintf('%s.%s', $time, $dataSignature); // send $finalSignature in the x-woosa-signature header
JavaScript / Node.js example (mind the slashes)
There is one subtle trap. PHP's json_encode escapes forward slashes (it writes
\/ instead of /), and JavaScript's JSON.stringify does not. If your signature is generated in JavaScript, you must add
that escaping by hand, otherwise the two sides compute different signatures and every request fails with 401.
const crypto = require('crypto');
const time = Math.floor(Date.now() / 1000);
const data = {
uri: uri, // path + query, starts with /
body: body, // exact request body string; "" for GET
time: time,
};
// JSON.stringify does NOT escape "/". Replace manually to match PHP's json_encode.
const dataToSign = JSON.stringify(data).replace(/\//g, '\\/');
const dataSignature = crypto
.createHmac('sha256', secret) // secret = your woosa_secret
.update(dataToSign)
.digest('base64');
const finalSignature = `${time}.${dataSignature}`;
The number one cause of "it says 401 and I do not know why": the string you signed does not exactly match the
request you sent. The body you sign must be byte-for-byte the same text you put in the request. The uri you sign must include the query string and start with /. And in JavaScript, remember the slash escaping.
Part 4: Connect your merchant account
Now you link a real account, identified by an email address. This is a two-step, signed exchange.
4a. Ask for a verification code
POST /email-verification-messages
Body:
{ "email": "merchant@example.com" }
This emails a short code to the merchant. Success is 204 No Content.
4b. Create or connect your Woosa Payments UI account to the shop
PUT /woocommerce/adyen/backoffice-user
Body:
{ "email": "merchant@example.com", "code": "123456" }
The code is what arrived by email. Please note, that code's lifetime is only 1 minute! On success (204), the account is connected. From here, the account-level actions (contractors,
stores) become available.
Part 5: Set up a legal entity and a store, then onboard
Before you can take money you need a store attached to a contractor. A contractor is the legal entity that actually gets paid: a company or an individual. Adyen has to know who is receiving the funds, which is why this exists.
5a. See your contractors
GET /woocommerce/adyen/backoffice-user-contractors
Returns a list like:
[
{
"id": "3c55be36-0dae-4be8-8354-0ce07a8bb101",
"name": "My Company B.V.",
"country": "NL",
"type": "organization"
}
]
5b. Set the current contractor (required only if you want to bind an existing contractor, ignore it if you get an empty list in 5a)
PUT /woocommerce/adyen/contractor
Body:
{ "contractorId": "3c55be36-0dae-4be8-8354-0ce07a8bb101" }
This call is mandatory if you want to access contractor related information. Skipping this step is the single most common cause of confusing errors.
For example, listing stores (GET /woocommerce/adyen/stores) will either fail
with an error if there is no connected contractor, or silently return the stores that belong to the wrong contractor, if your account has more than
one and if another contractor was connected to this shop before.
5c. Create a store
POST /woocommerce/adyen/stores
You describe both the contractor and the store. If the contractor does not exist yet, it is created automatically during this call and connected to the shop.
Please note that you should not provide real company information on DEV environment.
{
"contractor": {
"type": "organization",
"name": "My Company B.V.",
"owner": { "firstName": "John", "lastName": "Doe" },
"country": "NL"
},
"store": {
"label": "My Store",
"shopperStatement": "My Store NL",
"industryCode": "5411",
"phone": "+31612345678",
"currency": "EUR",
"address": {
"country": "NL",
"city": "Amsterdam",
"stateOrProvince": "",
"line1": "Keizersgracht 1",
"line2": "",
"line3": "",
"postalCode": "1012AB"
}
}
}
A couple of the fields deserve a plain-language note:
shopperStatementis the short text that appears on the customer's bank or card statement. This value can't be changed for a store in future so please be attentive.industryCodeis a standard category number for the kind of business (a "merchant category code"). You can fetch the valid list fromGET /woocommerce/adyen/industry-codes.countrycode you can pick fromGET /woocommerce/adyen/countries.
The response gives you a store id, for example ST32CSL223229G5NV6J3W4Z22. Write
this down. It goes into the URL of most payment calls from here on.
You can list existing stores at any time with GET /woocommerce/adyen/stores — as
long as the current contractor is set correctly first.
5d. Complete onboarding (identity and compliance checks)
Before real payments can flow, the merchant has to pass Adyen's checks (proof of identity, business details, accepting terms). This is called onboarding, and it is often referred to as KYC ("Know Your Customer").
Check where things stand:
GET /woocommerce/adyen/onboarding-status
A response tells you the status and, if something is missing, exactly what:
{
"status": "verification-required",
"errors": [
{
"problem": "'organization.doingBusinessAs' was missing.",
"actions": ["Add 'organization.doingBusinessAs' to legal entity"]
},
{
"problem": "Terms Of Service forms are not accepted.",
"actions": ["Accept TOS"]
}
]
}
To let the merchant fix these, generate a link and send them to it:
POST /woocommerce/adyen/onboarding-links
Response:
{ "uri": "https://onboarding-example.com/check-page/..." }
Redirect the merchant to that uri. They fill in whatever Adyen needs. When they
finish, Adyen returns them to your onboarding-redirect endpoint from Part 1c, which sends them back into your admin.
Re-check the status until it comes back clear.
Part 6: Choose which payment methods are active
6a. See what is available
GET /woocommerce/adyen/stores/{store_id}/checkout-payment-methods
Optional query parameters let you narrow the list:
shopper=customer_123to also get that specific customer's saved payment methods.country=NLto filter by country.currency=EURto filter by currency.
The response has two parts: paymentMethods (everything available to offer, such as
iDEAL, cards, Klarna, Apple Pay) and storedPaymentMethods (cards or methods this
shopper saved earlier, if you passed a shopper).
6b. Turn methods on or off
PUT /woocommerce/adyen/stores/{store_id}/payment-methods
You send the full list of methods you want active. This replaces the previous list, it does not add to it. So always send the complete set you want enabled.
A minimal example:
[
{ "type": "ideal" },
{ "type": "scheme" },
{ "type": "applepay", "applePay": { "domains": ["https://myshop.example.com"] } }
]
Some methods need extra configuration. You can find more details here. The response tells you, per method, whether it came out valid or returned an error you need to fix.
Part 7: Take a payment (the core loop)
This is the heart of it. A payment sometimes finishes in one step, and sometimes needs a second step because the shopper has to do something (approve in their banking app, pass a card security check, get redirected and come back). Your code should be ready for both.
7a. Create the payment
POST /woocommerce/adyen/stores/{store_id}/payments
Key fields:
channel: usually"web".returnUrl: where the shopper comes back to after any redirect (for example your order-received page).amount: an object withcurrencyandvalue. Important:valueis in minor units, the smallest unit of the currency. For euros that means cents. So 28.00 EUR is written as"value": 2800, not 28.paymentMethod: the method-specific data. For cards this contains the encrypted card fields produced by Adyen's Web Component (recommended way) or JWE (merchants with custom requirements).
Plus optional but commonly used fields: shopperReference (a stable id for the
customer, needed if you want to save their method), shopperEmail, billingAddress, lineItems (required for methods like
Klarna), browserInfo (needed for card security checks), and storePaymentMethod: true if you want to save the method for next time.
A trimmed iDEAL example:
{
"channel": "web",
"returnUrl": "https://myshop.example.com/checkout/order-received/592/",
"amount": { "currency": "EUR", "value": 2800 },
"paymentMethod": { "type": "ideal" },
"metadata": { "wc_order_id": 592 }
}
Tip: put your own order id in metadata (for example wc_order_id). Woosa echoes metadata back to you later, so this is how you match a
payment to the right order in your system.
7b. Read the result and react
The response always includes a resultCode. The two cases to handle:
resultCode: "Authorised"and no action: you are done. The payment succeeded. Save thepspReference(the unique payment id). You will need it for capturing, refunding, or cancelling later.- A response with an
actionobject (often withresultCode: "RedirectShopper"or similar): the shopper has one more step. Hand thatactionobject, unchanged, to Adyen's Web Component. It knows how to run the redirect or challenge. Do not try to interpret the action yourself, just pass it through.
Because the exact response shape varies by payment method, treat resultCode as
your primary signal, and lean on Adyen's own documentation for method-specific fields.
7c. Finish the extra step (only when there was an action)
After the shopper completes the redirect or challenge, the frontend gives you back some details. Send them here to finalise:
POST /woocommerce/adyen/stores/{store_id}/payment-details
{
"details": { "redirectResult": "X3XtfGC9!H4sIAAAAAAAA..." },
"metadata": { "wc_order_id": 593 }
}
Now you get a final resultCode (for example Authorised) with the confirmed amount and pspReference. This time the payment really is settled at the authorisation stage.
Part 8: After the payment (capture, refund, cancel, status)
These all use the pspReference from the payment, not the store id.
Capture
POST /woocommerce/adyen/payments/{psp_reference}/captures
Body:
{ "amount": { "currency": "EUR", "value": 2800 } }
Authorise vs capture, in plain words: when a payment is authorised, the money is reserved but not actually moved. Capturing is what pulls the money in. Many setups capture automatically, but if yours is set to manual capture you must call this, for example when you ship the goods. You can capture the full amount or a smaller part.
Refund
POST /woocommerce/adyen/payments/{psp_reference}/refunds
Body:
{ "amount": { "currency": "EUR", "value": 5000 } }
Gives money back to the shopper. Can be full or partial.
Cancel
POST /woocommerce/adyen/payments/{psp_reference}/cancels
Cancels a payment that was authorised but not yet captured. No body needed. Use this to release a reservation you are not going to charge (for example an order that fell through before shipping).
Get status updates
GET /woocommerce/adyen/updated-payments?after=2024-07-01 10:00:00
Payment statuses change over time (an authorisation gets captured, a refund settles, a chargeback arrives). This
endpoint returns every payment whose status changed in a time window. Poll it regularly (for example every hour) using after (required) and optionally before, and update the matching orders in your system using the metadata you attached
earlier.
Part 9: Housekeeping
Remove a saved payment method
POST /woocommerce/adyen/stores/{store_id}/unsubscribe-requests
{
"storedPaymentMethodId": "SGJC5J9LPTCT8W75",
"shopperReference": "32eeae5a-cc41-4bd3-967f-862c82bfec22"
}
Deletes a card or method a shopper had saved. Use this when a customer removes a saved card, or cancels a subscription.
GDPR: erase a shopper's data
POST /woocommerce/adyen/payments/{psp_reference}/subject-erasure-requests
Submits a request to erase the personal data tied to a specific payment. This is what you call to honour a "right to be forgotten" request.
Part 10: Go live
Do not point your integration at production on day one. Prove it out on the dev environment first, with a throwaway legal entity, and only onboard the real one once you have watched real test payments succeed end to end.
Step 1: Onboard a dummy legal entity on dev
On https://midlayer-dev.woosa.nl, walk through Part 5 with a test legal entity:
made-up (but validly formatted) company details, a test contractor, and a test store. Complete onboarding (Part 5d)
for this dummy entity so the store is actually able to take payments — Adyen's test environment will accept it
without real KYC documents.
This dummy entity's only job is to let you exercise the full flow without touching anything real. Do not reuse it once you go live.
Step 2: Run test payments
With the dummy entity's store, work through the core loop in Part 7 and Part 8 using Adyen's test card numbers and test iDEAL/redirect flows. At minimum, confirm your integration correctly handles:
- A straightforward payment that authorises immediately, with no extra shopper step.
- A payment that requires a redirect or challenge, including the return to
payment-details(Part 7c). - A capture, whether automatic or manual, depending on how your store is configured.
- A full refund and a partial refund.
- A cancel on a payment that has not yet been captured.
- Polling
updated-paymentsand correctly matching results back to your own orders usingmetadata. - A failed or declined payment, so you know your shop handles that gracefully too.
Only move on once every one of these behaves the way your shop expects, and your order statuses update correctly in each case.
Step 3: Onboard the live legal entity
Once the dev tests are clean, repeat Part 5 against production (https://midlayer.woosa.nl), this time with the merchant's real legal entity, real
contractor details, and real store. This is the entity that goes through genuine KYC — the merchant will need to
provide real identity and business documents during onboarding (Part 5d).
Remember: production has its own registration (Part 2) and its own woosa_secret.
Dev and production are entirely separate merchant accounts with separate credentials — a dev secret will not sign
valid requests against production, and vice versa.
Step 4: Switch over
- Point your shop's base URL at
https://midlayer.woosa.nl. - Confirm you are signing with the production
woosa_secret, not the dev one. - Re-check
onboarding-status(Part 5d) for the live legal entity to make sure it is fully verified before you rely on it. - Re-enable the payment methods you want live (Part 6b) — method configuration does not carry over from dev to production.
- Run one small real payment yourself first, end to end, before opening the doors to real customers.
Go-live checklist, in one line: dummy legal entity on dev → full test-payment run-through → real legal entity onboarded on production → switch the base URL and secret → one real test payment → live.
Quick reference: all endpoints
Base URL is https://midlayer.woosa.nl (or the -dev variant for testing). Every path below is signed except Register.
For full technical details on every field and parameter, see the API doc at wiki.woosashop.nl/rest-api-docs/woosa-payments.
Setup and account
| Do this | Method + path |
|---|---|
| Register your shop (unsigned) | POST /woocommerce/shops |
| Send an email verification code | POST /email-verification-messages |
| Connect the account | PUT /woocommerce/adyen/backoffice-user |
| List contractors | GET /woocommerce/adyen/backoffice-user-contractors |
| Set current contractor (required) | PUT /woocommerce/adyen/contractor |
| List reference: industry codes | GET /woocommerce/adyen/industry-codes |
| List reference: countries | GET /woocommerce/adyen/countries |
Stores and onboarding
| Do this | Method + path |
|---|---|
| List stores | GET /woocommerce/adyen/stores |
| Create a store | POST /woocommerce/adyen/stores |
| Check onboarding status | GET /woocommerce/adyen/onboarding-status |
| Create an onboarding link | POST /woocommerce/adyen/onboarding-links |
Payment methods
| Do this | Method + path |
|---|---|
| See available methods | GET /woocommerce/adyen/stores/{store_id}/checkout-payment-methods |
| Enable/disable methods | PUT /woocommerce/adyen/stores/{store_id}/payment-methods |
Payments
| Do this | Method + path |
|---|---|
| Create a payment | POST /woocommerce/adyen/stores/{store_id}/payments |
| Finish an extra shopper step | POST /woocommerce/adyen/stores/{store_id}/payment-details |
| Capture | POST /woocommerce/adyen/payments/{psp_reference}/captures |
| Refund | POST /woocommerce/adyen/payments/{psp_reference}/refunds |
| Cancel | POST /woocommerce/adyen/payments/{psp_reference}/cancels |
| Poll for status changes | GET /woocommerce/adyen/updated-payments |
| Remove a saved method | POST /woocommerce/adyen/stores/{store_id}/unsubscribe-requests |
| GDPR erasure | POST /woocommerce/adyen/payments/{psp_reference}/subject-erasure-requests
|
Endpoints your shop must expose (non-WooCommerce only)
| Woosa calls this on your shop | Method + path |
|---|---|
| Read settings (Basic Auth) | GET /wp-json/wc/v3/settings/general |
| Save settings (Basic Auth) | POST /wp-json/wc/v3/settings/general/batch |
| Onboarding return (no auth) | GET /wp-json/woosa-payments/onboarding-redirect |
Common mistakes and how to avoid them
- Registering before building the callback endpoints. Registration immediately calls your GET and POST settings endpoints. If they are not live and returning the right shape, registration fails. Do Part 1 first.
- 401 on every signed request. Almost always a signature mismatch. Check that the body you signed
is exactly the body you sent, that the
uriincludes the query string and starts with/, and (in JavaScript) that you escaped the forward slashes. - Amounts off by a factor of 100.
valueis in minor units. 28.00 EUR is 2800. Do not send 28. - Sending a partial method list. The "enable methods" call replaces the whole list. Always send every method you want active, not just the new one.
- Losing the `woosa_secret`. Store it permanently and safely. It is the key to every signed request. There is no signing without it.
- Skipping “set current contractor”. This call is required, not optional if you have more than one contractor. Skip it and listing stores can error out or return stores from the wrong legal entity.
- Not saving the `pspReference`. You need it for capture, refund, and cancel. Save it the moment a payment is created.
- Going live without testing on dev first. Onboard a dummy legal entity on the dev environment and run through the full payment, capture, refund, and cancel flows before onboarding the real legal entity in production. See Part 10.
- Testing against production. Use the
-devbase URL while you build. Switch to production only when you are ready for real money.
Glossary
- Midlayer: the Woosa server that sits between your shop and Adyen. You send your requests here.
- Adyen: the payment processor that actually moves the money. You never call it directly.
- PSP reference (pspReference): the unique id Adyen gives a payment. Your handle for capturing, refunding, or cancelling it.
- Store id (store_id): the id of a store you created. It goes in the URL of most payment calls.
- Contractor: the legal entity (company or individual) that receives the money.
- woosa_secret: the secret key Woosa gives your shop during registration. Used to sign every request.
- Signature: a tamper-proof seal computed per request, proving it came from you and was not altered.
- HMAC-SHA256: the standard one-way scrambling function used to build the signature.
- Basic Auth: a simple API login where the caller sends a username and password. Woosa uses your key and secret this way when calling your shop back.
- Authorise: reserving the money without moving it yet.
- Capture: actually pulling in the money that was authorised.
- Onboarding / KYC: the identity and compliance checks a merchant must pass before taking real payments.
- Tokenise / stored payment method: saving a shopper's card or method so they can pay again later with one click, or for subscriptions.
- Minor units: the smallest unit of a currency. Cents for euros. 28.00 EUR is 2800.
- Metadata: free-form data (like your own order id) that you attach to a payment and Woosa gives back to you later, so you can match payments to orders.