Protect & Unprotect
Use the core 4Quays APIs to protect and unprotect payloads
The /protect and /unprotect operations are the core of 4Quays. This guide covers how to use them effectively.
Overview
protect— Accept a plaintext payload and return a JWE (JSON Web Encryption) envelope.unprotect— Accept a JWE envelope and return the plaintext.
The policy determines the encryption algorithm and destination key. The application never handles keys, selects algorithms, or understands the internal structure of the JWE envelope.
Protecting Payloads
Use /protect before sending data to an external service:
const response = await fetch('https://api.4quays.com/api/v1/protect', {
method: 'POST',
headers: {
'Authorization': `Bearer ${apiKey}`,
'Content-Type': 'application/json',
},
body: JSON.stringify({
payload: {
transferId: 'txn-12345',
sourceAccount: 'CA1234567890',
destinationIban: 'CA0987654321',
amount: 5000.00,
currency: 'CAD',
memo: 'Payroll deposit',
},
policyNumber: 'BANK-TRANSFER-POLICY',
}),
});
const data = await response.json();
// Send the JWE envelope to external service
await axios.post('https://bank-api.example.com/transfers', {
encryption: data.jwe,
metadata: { timestamp: new Date().toISOString() },
});
Unprotecting Payloads
Use /unprotect when receiving protected data from an external service:
// Receive JWE envelope from external service
const bankResponse = await axios.get('https://bank-api.example.com/statements');
const jweEnvelope = bankResponse.data.encryption;
const response = await fetch('https://api.4quays.com/api/v1/unprotect', {
method: 'POST',
headers: {
'Authorization': `Bearer ${apiKey}`,
'Content-Type': 'application/json',
},
body: JSON.stringify({
jwe: jweEnvelope,
policyNumber: 'BANK-STATEMENT-POLICY',
}),
});
const data = await response.json();
console.log(data.payload.transactions);
Policy Numbers
Every protect/unprotect call accepts an optional policy number:
// Each external service has its own policy
const policies = {
'bank-a-transfers': 'BANK-A-TRANSFER-001',
'bank-b-transfers': 'BANK-B-TRANSFER-001',
};
// Use the appropriate policy for each service
await protect(payload, policies['bank-a-transfers']);
If policyNumber is omitted, the API uses the policy bound to the authenticated API key. This is convenient when each API key is scoped to a single policy.
Policy numbers are created in the 4Quays dashboard when you configure the relationship between services.
Return Values
Protect Result
The /protect endpoint returns a response containing a jwe envelope:
const data = await protectResponse.json(); // data.jwe is a JWE Flattened JSON object — do not parse or modify // data.operations lists what was performed (e.g. ["encrypt"]) // data.requestId for tracing // Just pass the JWE along to the external service await sendToService(data.jwe);
Unprotect Result
The /unprotect endpoint returns the original plaintext in the payload field:
const data = await unprotectResponse.json(); // data.payload is your original data structure console.log(data.payload.transferId); // 'txn-12345' console.log(data.payload.amount); // 5000.00
Error Handling
Handle errors appropriately:
const response = await fetch('https://api.4quays.com/api/v1/protect', {
method: 'POST',
headers: {
'Authorization': `Bearer ${apiKey}`,
'Content-Type': 'application/json',
},
body: JSON.stringify({ payload, policyNumber: 'POLICY-123' }),
});
const data = await response.json();
if (!response.ok) {
const { code, message } = data.error;
if (code === 'POLICY_NOT_FOUND') {
console.error('Policy does not exist:', message);
} else if (code === 'POLICY_NOT_ACTIVE') {
console.error('Policy is not active:', message);
} else if (code === 'AUTHENTICATION_FAILED') {
console.error('Invalid API key:', message);
} else {
console.error('Unexpected error:', message);
throw new Error(message);
}
}
Payload Formats
4Quays accepts any JSON-serializable payload:
// Objects
{ payload: { key: 'value' } }
// Arrays
{ payload: [1, 2, 3] }
// Nested structures
{ payload: { user: { id: 1 }, items: [{ id: 1 }] } }
// Strings
{ payload: 'sensitive-token' }
Best Practices
- Don't inspect JWE envelopes — Treat them as opaque blobs
- Use consistent policy mapping — Map external services to policies systematically
- Handle errors gracefully — Different error types require different responses
- Log policy usage — Track which policies are used for debugging
- Test with passthrough mode — Verify business logic before adding crypto
What's Next
- Development vs Production — Understand the two modes
- Example Walkthrough — Complete integration example
- Error Handling — Detailed error codes