API Help Guide

API usage and setup guide

Needine integrates with systems you already use. This guide explains how to activate API keys, authenticate requests, and issue your first certificate with verifiable traceability.

1. Prerequisites

  • - Active Needine account.
  • - Role with API key permissions (typically ADMIN).
  • - An HTTP client environment (Postman, curl, or your backend).
  • - API base URL for your deployment.
  • - Rotated secret storage for API keys (Vault, AWS Secrets Manager, etc.).

Production defaults

  • - Base URL: https://api.needine.com
  • - Auth header: X-API-Key: ndi_...
  • - Content type: application/json

2. Quickstart in 6 steps

  1. 1Create an API key from Console > Administration > API Keys.
  2. 2Store the full key in your secrets manager (it is shown only once).
  3. 3Send the key in the X-API-Key header on every request.
  4. 4Register the AI model and vendor you use at /models and /vendors.
  5. 5Issue a certificate at /certificates with its evidences.
  6. 6Share the public verification link /verify/:id with third parties.

3. API key authentication

All machine-to-machine API calls must include the X-API-Key. Needine validates key prefix + SHA-256 hash and applies permissions from the key owner user.

Curl example

curl -X GET "https://your-api-domain/certificates?page=1&pageSize=20" \
  -H "X-API-Key: ndi_xxxxxxxxxxxxxxxxx" \
  -H "Content-Type: application/json"

Node.js fetch example

const res = await fetch("https://api.needine.com/certificates?page=1&pageSize=10", {
  headers: {
    "X-API-Key": process.env.NEEDINE_API_KEY,
    "Content-Type": "application/json"
  }
});

if (!res.ok) throw new Error(`HTTP ${res.status}`);
const data = await res.json();

4. Recommended API flow

Step A

Register vendor

POST /vendors

Step B

Register model

POST /models

Step C

Issue certificate

POST /certificates

Step D

Get traceability

GET /certificates/:id/provenance

Step E

Public verification

GET /verification/:id

5. Minimum payload to issue a certificate

This sample uses fields validated by the current API contract. Adjust by your workflow and always validate in Swagger before go-live.

Valid certificateType values

ai_report | ai_audit | ai_model_card | ai_dataset_card | ai_evaluation | generic

{
  "certificateType": "ai_report",
  "reportName": "Quarterly AI Risk Summary",
  "signerName": "Maria Lopez",
  "issuingCompany": "Acme Consulting",
  "inputEvidence": [
    {
      "evidenceType": "input",
      "sha256Hash": "b7c4f4...64hex",
      "mimeType": "application/json",
      "filename": "input.json",
      "storageMode": "hash_only"
    }
  ],
  "outputEvidence": [
    {
      "evidenceType": "output",
      "sha256Hash": "a99d2a...64hex",
      "mimeType": "application/pdf",
      "filename": "output.pdf",
      "storageMode": "hash_only"
    }
  ],
  "model": {
    "provider": "openai",
    "modelName": "gpt-4o"
  }
}

6. End-to-end examples for backend teams

Use one of these snippets to issue and verify certificates from your integration layer.

curl (issue certificate)

curl -X POST "https://api.needine.com/certificates" \
  -H "X-API-Key: ndi_xxxxxxxxxxxxxxxxx" \
  -H "Content-Type: application/json" \
  -d '{
    "certificateType": "ai_report",
    "signerName": "Maria Lopez",
    "issuingCompany": "Acme Consulting",
    "inputEvidence": [{"sha256Hash": "b7c4...", "evidenceType": "input"}],
    "outputEvidence": [{"sha256Hash": "a99d...", "evidenceType": "output"}],
    "model": {"provider": "openai", "modelName": "gpt-4o"}
  }'

JavaScript SDK

import { NeedineClient } from "@needine/sdk";

const client = new NeedineClient({ apiKey: process.env.NEEDINE_API_KEY });
const created = await client.createCertificate({
  certificateType: "ai_report",
  signerName: "Maria Lopez",
  issuingCompany: "Acme Consulting",
  inputEvidence: [{ sha256Hash: "b7c4...", evidenceType: "input" }],
  outputEvidence: [{ sha256Hash: "a99d...", evidenceType: "output" }],
  model: { provider: "openai", modelName: "gpt-4o" }
});

const verification = await client.verifyCertificate(created.certificateId);
console.log(created.certificateId, verification.valid, verification.trustLevel);

Python SDK

from needine import NeedineClient

client = NeedineClient(api_key="ndi_xxx", base_url="https://api.needine.com")
created = client.create_certificate({
    "certificateType": "ai_report",
    "signerName": "Maria Lopez",
    "issuingCompany": "Acme Consulting",
    "inputEvidence": [{"sha256Hash": "b7c4...", "evidenceType": "input"}],
    "outputEvidence": [{"sha256Hash": "a99d...", "evidenceType": "output"}],
    "model": {"provider": "openai", "modelName": "gpt-4o"}
})

verification = client.verify_certificate(created["certificateId"])
print(created["certificateId"], verification["valid"], verification["trustLevel"])

7. Webhooks (optional)

Webhooks let your backend react in near real-time when certificate state changes. Register endpoint URLs from the Console (or API), subscribe to events, and process callbacks asynchronously in your integration layer.

Webhook management endpoints

  • - POST /webhooks register endpoint (returns secret once).
  • - GET /webhooks list endpoints + latest delivery info.
  • - DELETE /webhooks/:id remove endpoint.
  • - GET /webhooks/:id/deliveries?page=1&pageSize=20 inspect delivery logs.

Supported event names

certificate.issued,certificate.revoked,anchor.confirmed,trust.updated

Current production triggers actively dispatch certificate lifecycle events: certificate.issued and certificate.revoked.

Delivery contract

  • - Method: POST
  • - Content-Type: application/json
  • - Timeout per attempt: 10s
  • - Retries: 3 attempts with backoff 1s, 4s, 9s
  • - Success criteria: any HTTP 2xx response
  • - Recommended receiver behavior: idempotent processing keyed by event + certificate ID.

Headers and body sent by Needine

POST https://your-system.example/webhooks/needine
Content-Type: application/json
X-Needine-Event: certificate.issued
X-Needine-Signature: sha256=<hex>

{
  "event": "certificate.issued",
  "payload": {
    "certificateId": "cert_xxx",
    "certificateType": "ai_report",
    "status": "issued",
    "issuedAt": "2026-03-18T19:48:08.800Z",
    "signerName": "Maria Lopez",
    "issuingCompany": "Acme Consulting",
    "verificationUrl": "https://needine.com/verify/cert_xxx"
  },
  "timestamp": "2026-03-18T19:48:09.120Z"
}

Signature verification (Node.js)

import crypto from "crypto";

const rawSecret = process.env.NEEDINE_WEBHOOK_SECRET;
const signatureHeader = req.headers["x-needine-signature"]; // sha256=<hex>
const rawBody = requestRawBodyAsString;

const signingKey = crypto.createHash("sha256").update(rawSecret).digest("hex");
const expected = crypto.createHmac("sha256", signingKey).update(rawBody).digest("hex");
const received = String(signatureHeader || "").replace("sha256=", "");

if (!crypto.timingSafeEqual(Buffer.from(expected, "hex"), Buffer.from(received, "hex"))) {
  throw new Error("Invalid webhook signature");
}

Signature verification (Python)

import hashlib
import hmac

raw_secret = os.environ["NEEDINE_WEBHOOK_SECRET"]
signature_header = request.headers.get("X-Needine-Signature", "")
raw_body = request.get_data(as_text=True)

signing_key = hashlib.sha256(raw_secret.encode()).hexdigest()
expected = hmac.new(signing_key.encode(), raw_body.encode(), hashlib.sha256).hexdigest()
received = signature_header.replace("sha256=", "")

if not hmac.compare_digest(expected, received):
    raise ValueError("Invalid webhook signature")

8. AI vendors API

Track third-party AI vendors, their DPA status, certifications, and risk scores. Use these endpoints to maintain supply chain transparency as required by the EU AI Act.

Vendor management endpoints

  • - POST /vendors create a vendor (name, type, website, contactEmail).
  • - GET /vendors list vendors with optional filters (type, reviewStatus, dpaStatus).
  • - PUT /vendors/:id update vendor info, DPA status, certifications, risk score.
  • - DELETE /vendors/:id remove a vendor.
  • - GET /vendors/:id/models list AI models linked to a specific vendor.
  • - GET /vendors/export export vendor registry as CSV or JSON.

Vendor types

API_PROVIDER,PLATFORM,SELF_HOSTED,OPEN_SOURCE

DPA status workflow

NOT_REVIEWEDPENDING_SIGNATURESIGNEDEXPIRED

9. Model inventory and performance API

Extend model records with GPAI classification, inventory fields, and performance evaluations. Needine automatically detects metric drift between consecutive evaluations.

Model inventory endpoints

  • - PUT /models/:id/gpai-classification set GPAI status and compute threshold.
  • - PUT /models/:id/inventory update use case, department, responsible person, risk level.
  • - GET /models/inventory/export export full model registry as CSV or JSON.

Model performance endpoints

  • - POST /models/:modelId/performance record an evaluation (accuracy, precision, recall, F1, AUC).
  • - GET /models/:modelId/performance list evaluation history (paginated).
  • - GET /models/:modelId/performance/latest get the most recent evaluation.
  • - GET /models/:modelId/performance/drift compare the latest two evaluations for metric drift.

Example: record a performance evaluation

curl -X POST "https://api.needine.com/models/model_xxx/performance" \
  -H "X-API-Key: ndi_xxxxxxxxxxxxxxxxx" \
  -H "Content-Type: application/json" \
  -d '{
    "accuracy": 0.94,
    "precision": 0.91,
    "recall": 0.89,
    "f1Score": 0.90,
    "auc": 0.96,
    "datasetName": "Q1-2026-validation",
    "datasetSize": 12500,
    "evaluatedBy": "data-science-team",
    "notes": "Quarterly model evaluation"
  }'

10. EU AI Act compliance API

The compliance API covers each EU AI Act obligation with dedicated endpoints. All records are linked to certificates and models within your organization.

Transparency (Art. 13, 14, 50)

  • - POST /certificates/:id/transparency create a transparency record.
  • - GET /certificates/:id/transparency get the transparency record.
  • - PUT /certificates/:id/transparency update transparency info.

Fields: interactionType (CHATBOT, DEEPFAKE, EMOTION, BIOMETRIC, GENERATED_CONTENT), humanOversightType (HITL, HOTL, HIC), disclosure, override process, stop mechanism.

Technical Documentation (Art. 11, Annex IV)

  • - POST /certificates/:id/technical-doc create technical documentation.
  • - GET /certificates/:id/technical-doc retrieve documentation.
  • - PUT /certificates/:id/technical-doc update documentation fields.
  • - GET /certificates/:id/technical-doc/annex-iv get Annex IV compliance score.

Fields: system name, intended purpose, deployers, design specs, data governance, validation, performance metrics, risk mitigations.

FRIA — Fundamental Rights Impact Assessment (Art. 6, 27)

  • - POST /compliance/fria create a FRIA.
  • - GET /compliance/fria list all FRIAs.
  • - PUT /compliance/fria/:id update FRIA details.
  • - PATCH /compliance/fria/:id/review mark as reviewed.

Impact categories: privacy, non-discrimination, freedom, dignity, consumer protection. Status: DRAFT → COMPLETED → REVIEWED.

Risk Management, Monitoring, Literacy & Incidents

  • - POST/PUT /compliance/risk-management manage risks by phase (design → post-market).
  • - POST/PUT /compliance/monitoring-plans create post-market monitoring plans.
  • - POST/GET /compliance/literacy record AI literacy training completions.
  • - POST/PUT /compliance/incidents report compliance incidents.
  • - POST/PUT /compliance/qms quality management system records.

11. Blockchain anchoring API

Certificates are anchored on Arbitrum One via Merkle trees. Use these endpoints to trigger anchoring manually or verify an existing anchor on-chain.

Anchoring endpoints

  • - POST /anchors/trigger trigger blockchain anchoring for pending certificates.
  • - GET /anchors/:id/verify verify an anchor on-chain (returns Merkle root, tx hash, block number).

Anchor status: PENDING → SUBMITTED → CONFIRMED (or FAILED with automatic retries).

12. Reports and analytics API

Generate compliance and operational reports programmatically. All report endpoints accept optional date range query parameters.

Available report endpoints

  • - GET /reports/eu-ai-act risk classification by certificate type.
  • - GET /reports/eu-ai-act-full full compliance bundle (all modules combined).
  • - GET /reports/compliance-score overall compliance percentage.
  • - GET /reports/fria-summary FRIA count by status.
  • - GET /reports/risk-management-summary risks by phase.
  • - GET /reports/transparency-summary transparency records count.
  • - GET /reports/monitoring-summary active monitoring plans.
  • - GET /reports/incidents-summary incidents by status.
  • - GET /reports/qms-summary QMS documentation status.
  • - GET /reports/literacy-summary AI training completion percentage.
  • - GET /reports/technical-doc-coverage technical documentation completeness.
  • - GET /reports/model-performance model performance stats.
  • - GET /reports/gdpr-trail GDPR audit trail.
  • - GET /reports/declaration export compliance declaration.

13. Common errors and fixes

401 Unauthorized

Cause: API key missing, revoked, or expired.

Fix: Check the X-API-Key header and key status in Console.

403 Forbidden

Cause: The API key does not have scope for this action.

Fix: Create a key with the correct scopes or adjust owner permissions.

404 Not Found

Cause: Invalid certificate ID or out-of-organization resource.

Fix: Confirm you are using the exact certificateId returned at issuance.

429 Too Many Requests

Cause: Too many requests in a short interval.

Fix: Apply retries with exponential backoff and retry queues.

Integration playbook

How to integrate Needine based on the customer's IT infrastructure

Needine plugs into the customer's existing systems: it does not require replacing the ERP, CRM, document platform, or AI pipeline. Identify your scenario in the table and follow the recommended pattern below.

Customer typeHow they call NeedineGo to pattern
Modern customer with their own backendDirect REST API or SDKPattern A
Customer with Java / .NET / Python / Node stackSDK or HTTP clientPattern B
Customer with manual or low-code processesMiddleware / connectorPattern C
Customer with ERP / CRMAdapter between ERP and NeedinePattern D
Customer with closed infrastructurePrivate integration, VPN, allowlist or dedicated deploymentPattern E
Customer without enough technical capacityAssisted integration servicePattern F
Before you start: run a 60-90 min Integration Assessment to answer: which event triggers certification?, which evidence can be hashed in place?, can the system make outbound HTTPS?, can it receive webhooks?, are there SSO / proxy / firewall / data residency constraints?, who signs or approves?, where is the certificateId stored?

Pattern A — Modern customer with their own backend

Direct call to the REST API or use of the official SDK. This is the fastest pattern (1-3 days): event generated → local hash of evidence → POST to Needine → store certificateId → subscribe to webhooks.

Flow diagram

[Customer backend]
   │ 1. Generates AI output
   │ 2. sha256(input) + sha256(output)
   │ 3. POST /certificates  (X-API-Key)
   ▼
[Needine API] -- 4. Returns certificateId, verificationUrl, trustLevel
   │
   │ 5. anchor.confirmed (HMAC-signed webhook)
   ▼
[Customer backend] stores certificateId in its DB / ERP / CRM

Node / TypeScript SDK

import { NeedineClient } from "@needine/sdk";
import crypto from "crypto";

const client = new NeedineClient({ apiKey: process.env.NEEDINE_API_KEY! });
const sha256 = (buf: Buffer) => crypto.createHash("sha256").update(buf).digest("hex");

const cert = await client.createCertificate({
  certificateType: "ai_report",
  signerName: "Maria Lopez",
  issuingCompany: "Acme SaaS",
  inputEvidence:  [{ sha256Hash: sha256(inputBuffer),  evidenceType: "input"  }],
  outputEvidence: [{ sha256Hash: sha256(outputBuffer), evidenceType: "output" }],
  model: { provider: "openai", modelName: "gpt-4o" },
});

await db.certificates.update({ where: { jobId }, data: { needineId: cert.certificateId } });

Python SDK

from needine import NeedineClient
import hashlib, os

client = NeedineClient(api_key=os.environ["NEEDINE_API_KEY"])

def sha256(b: bytes) -> str:
    return hashlib.sha256(b).hexdigest()

cert = client.create_certificate({
    "certificateType": "ai_report",
    "signerName": "Maria Lopez",
    "issuingCompany": "Acme SaaS",
    "inputEvidence":  [{"sha256Hash": sha256(input_bytes),  "evidenceType": "input"}],
    "outputEvidence": [{"sha256Hash": sha256(output_bytes), "evidenceType": "output"}],
    "model": {"provider": "openai", "modelName": "gpt-4o"},
})
print(cert["certificateId"], cert.get("verificationUrl"))

Pattern B — Languages without an official SDK (Java, .NET, Go, PHP, Ruby)

While we publish native SDKs, any standard HTTP client works. The API is REST + JSON, with OpenAPI available at /api/docs, which lets you generate clients automatically with openapi-generator.

Java 17+ (HttpClient)

import java.net.http.*;
import java.net.URI;

var body = """
{
  "certificateType": "ai_report",
  "signerName": "Maria Lopez",
  "issuingCompany": "Acme Industrial",
  "inputEvidence":  [{"sha256Hash":"%s","evidenceType":"input"}],
  "outputEvidence": [{"sha256Hash":"%s","evidenceType":"output"}],
  "model": {"provider":"openai","modelName":"gpt-4o"}
}
""".formatted(inputHash, outputHash);

var req = HttpRequest.newBuilder(URI.create("https://api.needine.com/certificates"))
    .header("X-API-Key", System.getenv("NEEDINE_API_KEY"))
    .header("Content-Type", "application/json")
    .POST(HttpRequest.BodyPublishers.ofString(body))
    .build();

var res = HttpClient.newHttpClient().send(req, HttpResponse.BodyHandlers.ofString());

.NET 8 (HttpClient)

using System.Net.Http.Json;

var http = new HttpClient { BaseAddress = new Uri("https://api.needine.com/") };
http.DefaultRequestHeaders.Add("X-API-Key", Environment.GetEnvironmentVariable("NEEDINE_API_KEY"));

var payload = new {
    certificateType = "ai_report",
    signerName = "Maria Lopez",
    issuingCompany = "Acme Bank",
    inputEvidence  = new[] { new { sha256Hash = inputHash,  evidenceType = "input"  } },
    outputEvidence = new[] { new { sha256Hash = outputHash, evidenceType = "output" } },
    model = new { provider = "openai", modelName = "gpt-4o" }
};

var res = await http.PostAsJsonAsync("certificates", payload);
res.EnsureSuccessStatusCode();
var cert = await res.Content.ReadFromJsonAsync<Dictionary<string, object>>();

Go

payload := map[string]any{
    "certificateType": "ai_report",
    "signerName":      "Maria Lopez",
    "issuingCompany":  "Acme Logistics",
    "inputEvidence":   []map[string]string{{"sha256Hash": inputHash,  "evidenceType": "input"}},
    "outputEvidence":  []map[string]string{{"sha256Hash": outputHash, "evidenceType": "output"}},
    "model":           map[string]string{"provider": "openai", "modelName": "gpt-4o"},
}
b, _ := json.Marshal(payload)
req, _ := http.NewRequest("POST", "https://api.needine.com/certificates", bytes.NewReader(b))
req.Header.Set("X-API-Key", os.Getenv("NEEDINE_API_KEY"))
req.Header.Set("Content-Type", "application/json")
resp, err := http.DefaultClient.Do(req)

PHP 8

$payload = [
  "certificateType" => "ai_report",
  "signerName"      => "Maria Lopez",
  "issuingCompany"  => "Acme Legal",
  "inputEvidence"   => [["sha256Hash" => $inputHash,  "evidenceType" => "input"]],
  "outputEvidence"  => [["sha256Hash" => $outputHash, "evidenceType" => "output"]],
  "model"           => ["provider" => "openai", "modelName" => "gpt-4o"],
];

$ch = curl_init("https://api.needine.com/certificates");
curl_setopt_array($ch, [
  CURLOPT_RETURNTRANSFER => true,
  CURLOPT_POST           => true,
  CURLOPT_HTTPHEADER     => ["X-API-Key: " . getenv("NEEDINE_API_KEY"), "Content-Type: application/json"],
  CURLOPT_POSTFIELDS     => json_encode($payload),
]);
$cert = json_decode(curl_exec($ch), true);
OpenAPI generator:
openapi-generator-cli generate -i https://api.needine.com/api/docs-json \
  -g java -o ./needine-java
  # csharp-netcore, go, php, ruby, rust, kotlin, typescript-axios

Pattern C — Manual or low-code processes (Make, Zapier, n8n, Power Automate)

For customers without a development team, any automation platform can call Needine as a generic HTTP module. The customer only configures the URL, the API key, and the JSON.

Make / Zapier

  • Trigger: new file in Drive / Dropbox / SharePoint.
  • Step: HTTP module → POST /certificates.
  • Header: X-API-Key.
  • Output: certificateId, verificationUrl.
  • Action: append URL to file or send by email.

n8n (self-hosted)

  • Crypto node → SHA-256 of the file.
  • HTTP Request node → POST to Needine.
  • Webhook node → receive certificate.issued.
  • Set node → update your database / Notion / Airtable.

Microsoft Power Automate

  • Trigger: When a file is created (SharePoint).
  • Compute hash with sha256(...) function.
  • HTTP action to /certificates.
  • Update file metadata with certificateId.

Google Apps Script

  • Trigger: onFormSubmit / onFileCreate.
  • UrlFetchApp.fetch() with headers.
  • Save response in Sheets / Drive.

Power Automate example (HTTP action)

Method:  POST
URI:     https://api.needine.com/certificates
Headers: X-API-Key   : @{parameters('needine_api_key')}
         Content-Type: application/json
Body:
{
  "certificateType": "ai_report",
  "signerName": "@{triggerBody()?['Editor']?['DisplayName']}",
  "issuingCompany": "@{parameters('company')}",
  "inputEvidence":  [{"sha256Hash": "@{outputs('Hash_input')}",  "evidenceType": "input"}],
  "outputEvidence": [{"sha256Hash": "@{outputs('Hash_output')}", "evidenceType": "output"}],
  "model": { "provider": "openai", "modelName": "gpt-4o" }
}

Pattern D — Customer with ERP / CRM (SAP, Salesforce, Dynamics, ServiceNow, Odoo)

The ERP core is not modified. A lightweight adapter (microservice or serverless function) is introduced to listen to the ERP event, normalize the payload, compute hashes, call Needine, and return the certificateId to the ERP to be saved in a custom field.

Adapter architecture

[ERP / CRM]
   │ Event (BAPI / Outbound Message / Business Rule / Webhook)
   ▼
[Needine adapter]   ← customer or Needine microservice
   │ • ERP fields → Needine schema mapping
   │ • SHA-256 computation
   │ • Retries + queue (idempotency by externalId)
   │ • Vault for API key
   ▼
[Needine API]
   │
   │ signed webhook
   ▼
[Adapter]  →  Update ERP record (custom field: needine_certificate_id)

SAP S/4HANA

  • SAP CPI / PI/PO with REST iflow.
  • OData Service exposes event → CPI calls Needine.
  • Custom field ZNEEDINE_CERTID in the master table.

Salesforce

  • Apex callout with Named Credential (manages API key).
  • Trigger after insert/update → async call (@future or Queueable).
  • Platform Event to receive Needine webhooks.

Microsoft Dynamics 365

  • Power Automate flow (cloud) or C# plugin (sandbox).
  • Azure Function as adapter, invoked by Dataverse webhook.

ServiceNow

  • Business Rule + REST Message v2.
  • Custom IntegrationHub Spoke.
  • Inbound REST to receive webhooks.

Odoo

  • Custom Python module using needine-sdk.
  • Hook on create() or action_done().

Document management

  • SharePoint / M-Files / Alfresco / DocuWare.
  • Hook on file checkin → certify and save URL.

Apex (Salesforce) — example

public with sharing class NeedineService {
  @future(callout=true)
  public static void certify(Id reportId) {
    Report__c r = [SELECT Id, OutputHash__c, InputHash__c FROM Report__c WHERE Id = :reportId];

    HttpRequest req = new HttpRequest();
    req.setEndpoint('callout:Needine/certificates');
    req.setMethod('POST');
    req.setHeader('Content-Type', 'application/json');
    req.setBody(JSON.serialize(new Map<String, Object>{
      'certificateType' => 'ai_report',
      'signerName'      => UserInfo.getName(),
      'issuingCompany'  => 'Acme',
      'inputEvidence'   => new List<Object>{ new Map<String,String>{ 'sha256Hash' => r.InputHash__c,  'evidenceType' => 'input'  } },
      'outputEvidence'  => new List<Object>{ new Map<String,String>{ 'sha256Hash' => r.OutputHash__c, 'evidenceType' => 'output' } },
      'model'           => new Map<String,String>{ 'provider' => 'openai', 'modelName' => 'gpt-4o' }
    }));

    HttpResponse res = new Http().send(req);
    Map<String,Object> body = (Map<String,Object>) JSON.deserializeUntyped(res.getBody());
    update new Report__c(Id = reportId, NeedineCertificateId__c = (String) body.get('certificateId'));
  }
}

Pattern E — Closed infrastructure (banking, healthcare, defense, public sector)

When the customer has strong network restrictions, data residency, or compliance requirements, additional mechanisms apply:

IP allowlist / firewall

Needine publishes a stable outbound IP range. The customer adds it to their firewall to allow inbound webhooks and API responses.

Site-to-site VPN / private link

IPsec tunnel or AWS PrivateLink / Azure Private Endpoint so traffic never goes over the public Internet.

Corporate proxy with MITM

The SDK accepts a custom baseUrl and CA bundle. Recommended: pin the Needine fingerprint and bypass the proxy for webhooks (already validated with HMAC).

mTLS

Available on demand. Each side presents an X.509 certificate; useful for regulated sectors that do not accept API keys as the sole factor.

Dedicated / on-premise deployment

Official Docker images of the Needine backend + trust engine + customer Postgres. Optional blockchain anchoring. 100% residency in customer infrastructure.

No inbound webhooks (polling mode)

If the customer's network does not accept callbacks, their system polls every N minutes: GET /certificates?updatedAfter=….

Sensitive data (GDPR / secrets)

The raw payload never leaves the customer: only SHA-256 hashes and metadata are sent. Compatible with the right to erasure (PII off-chain, hash on-chain).

Corporate SSO (Azure AD, Okta, Keycloak)

Bidirectional OAuth2 / OIDC integration. Roadmap: SAML 2.0 for legacy customers.

On-premise deployment (minimal docker-compose)

services:
  needine-api:
    image: registry.needine.com/needine-api:stable
    env_file: .env.needine
    depends_on: [postgres]
    ports: ["8080:3000"]
  trust-engine:
    image: registry.needine.com/trust-engine:stable
    env_file: .env.needine
  postgres:
    image: postgres:16
    environment:
      POSTGRES_DB: needine
      POSTGRES_USER: needine
      POSTGRES_PASSWORD_FILE: /run/secrets/db
    volumes: ["pgdata:/var/lib/postgresql/data"]
volumes: { pgdata: {} }

Polling (when no webhooks are available)

curl -G "https://api.needine.com/certificates" \
  -H "X-API-Key: $NEEDINE_API_KEY" \
  --data-urlencode "updatedAfter=$(cat .needine_cursor)" \
  --data-urlencode "pageSize=100"

Pattern F — Customer without technical capacity (assisted integration service)

If the customer has no development team, Needine delivers a turn-key solution that requires no programming:

  • **Needine web portal**: the user uploads the file, the system computes the hash in the browser and issues the certificate without any coding.
  • **Pre-configured connector** delivered by Needine or a partner: a Docker image or an n8n app with ready-made flows; the customer only enters their API key.
  • **Make / Zapier / Power Automate templates** published: import and connect.
  • **Email-to-certify**: send the evidence as an attachment to a dedicated address and receive the certificate by email.
  • **Managed service**: Needine or a partner integrator runs the solution for the customer (assisted Enterprise package).

Three commercial integration tiers

TierTimeCustomer profile
QuickStart API1-3 daysModern backend, 1 generalist developer (Pattern A/B)
Assisted connector1-3 weeksERP/CRM, low-code (Pattern C/D)
Enterprise4-12 weeksRestricted infra, on-prem, complex SSO (Pattern E/F)

Computing SHA-256 locally (evidence never leaves)

Needine receives the hash, not the content. Compute SHA-256 inside the customer's network and send only the lowercase hexadecimal digest (64 characters).

# bash
sha256sum file.pdf | awk '{print $1}'
# PowerShell
(Get-FileHash file.pdf -Algorithm SHA256).Hash.ToLower()
// Node
crypto.createHash("sha256").update(buf).digest("hex");
# Python
hashlib.sha256(data).hexdigest()
// Java
MessageDigest.getInstance("SHA-256").digest(bytes); // -> bytesToHex
// C#
Convert.ToHexString(SHA256.HashData(bytes)).ToLowerInvariant();
// Browser (no upload required)
const buf = await file.arrayBuffer();
const h = await crypto.subtle.digest("SHA-256", buf);
[...new Uint8Array(h)].map(b => b.toString(16).padStart(2,"0")).join("");
// Go
sum := sha256.Sum256(data)
hex.EncodeToString(sum[:])

Integration best practices

Idempotency

Send the Idempotency-Key: <your-event-uuid> header. If you retry, no duplicate certificates will be created.

Retries with backoff

Retry only 429, 502, 503, 504, and network errors. Exponential backoff 1s, 2s, 4s, 8s (max. 5 attempts).

Rate limiting

Respect X-RateLimit-Remaining and Retry-After headers. Configure a client-side semaphore.

Pagination

?page=N&pageSize=20 (max 100). The response includes total, page, pageSize.

API key storage

Vault / Azure Key Vault / AWS Secrets Manager / GCP Secret Manager. Never in repo or frontend.

Rotation

API keys: quarterly rotation. OAuth: POST /oauth/clients/:id/rotate-secret. Webhooks: regenerate the secret when security requests it.

Observability

Log the X-Request-Id returned by the API; it eases support. Health endpoint: /health.

Webhook validation

Verify HMAC before processing. Return 2xx in under 5s; any heavy logic goes to a queue.

Sandbox, OpenAPI, and public verification

  • **Sandbox**: https://sandbox.api.needine.com — issues test certificates, free, with no real blockchain anchoring.
  • **Swagger / OpenAPI**: /api/docs and JSON at /api/docs-json to generate clients.
  • **Postman collection**: downloadable from the developer portal.
  • **Public verification without auth**: GET /verification/{certificateId} — useful for auditors or third parties.
  • **Audit rooms**: temporary tokens (POST /audit-rooms) that grant read-only access to an auditor for X hours.

Integration checklist (before going to production)

  • Identified the business event that triggers certification
  • API key created and stored in the customer's vault
  • SHA-256 hash computed locally; raw content never leaves the customer
  • Source-system field mapping to the Needine schema documented
  • certificateId persisted in the source system (field or table)
  • Webhooks configured with verified HMAC, or active polling if no inbound callback
  • Idempotency-Key implemented on every POST /certificates
  • Retries with exponential backoff only on 429/5xx
  • Logs include X-Request-Id for support
  • Sandbox validated with at least 10 test certificates before switching to production
  • Rate limit measured and sized to the actual expected volume
  • API key and webhook secret rotation plan
  • Public verification tested by an external auditor
  • DPA / contracts signed if personal data is involved

Want us to help you integrate?

Book a 60-90 minute Integration Assessment with our technical team. We leave with the chosen pattern, the adapter defined, and a deployment plan.

Open Swagger / OpenAPI