Node.js Guide

Node.js integration

Node.js ≥ 18 (native fetch). This is the exact pattern behind the mini-SDK.

1. Set up the client

const BASE = 'https://api.ethiolink-consent.et';

async function call(method, path, body, apiKey) {
  const res = await fetch(BASE + path, {
    method,
    headers: {
      'Content-Type': 'application/json',
      ...(apiKey ? { Authorization: `Bearer ${apiKey}` } : {}),
    },
    body: body ? JSON.stringify(body) : undefined,
  });
  const json = await res.json().catch(() => ({}));
  if (!res.ok) throw new Error(`${json.error?.code}: ${json.error?.message}`);
  return json;
}

2. Request consent

// "Please show me 30 days of Alemu's transaction history"
const request = await call('POST', '/api/consent/request', {
  user_fayda_id: 'FAYDA-847291',          // or user_email / user_id
  purpose: 'Loan eligibility assessment',
  data_categories_requested: ['transaction_history', 'mobile_money'],
  duration_days: 30,
  // Required ONLY for automated decision-making (PDPP Art. 24(1)(m)):
  // involves_automation: true,
  // automation_description: 'A scoring model estimates eligibility.',
}, process.env.ETHIOLINK_API_KEY);

const consentId = request.request.public_id; // cr_...
// Alemu now reviews it in her dashboard or by SMS reply.

3. Verify a token before touching data

const q = new URLSearchParams({ token: consentToken, reason: 'loan_application' });
const verdict = await call('GET', `/api/consent/active?${q}`, undefined, apiKey);

if (!verdict.active) {
  // status: 'revoked' | 'expired' | 'not_found' | 'wrong_institution'
  throw new Error(`Consent not usable: ${verdict.status}`);
}
// verdict.automation?.objection === true  -> route to human review
// verdict.data_categories                 -> exactly the granted categories

4. Retrieve encrypted data

const q = new URLSearchParams({ token: consentToken, reason: 'loan_application' });
const data = await call('GET', `/api/data/retrieve?${q}`, undefined, apiKey);
// data.transfers[].encrypted_data   -> opaque blob, decrypt with your key
// data.transfers[].source_institution

5. Webhook signature verification

import crypto from 'node:crypto';

function verifyWebhook(reqBody, signature, timestamp, secret) {
  const expected = crypto
    .createHmac('sha256', secret)
    .update(`${timestamp}.${JSON.stringify(reqBody)}`)
    .digest('hex');
  return crypto.timingSafeEqual(Buffer.from(signature), Buffer.from(expected));
}
// Headers: X-EthioLink-Timestamp, X-EthioLink-Signature

← All guides · Need the full reference? docs/API.md