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
- 1Create an API key from Console > Administration > API Keys.
- 2Store the full key in your secrets manager (it is shown only once).
- 3Send the key in the X-API-Key header on every request.
- 4Create or register the AI model you use at /models.
- 5Issue a certificate at /certificates with its evidences.
- 6Share the public verification link /verify/:id with third parties.
3. API key authentication
All machine-to-machine API calls must include theX-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 model
POST /models
Step B
Issue certificate
POST /certificates
Step C
Get traceability
GET /certificates/:id/provenance
Step D
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 /webhooksregister endpoint (returns secret once). - -
GET /webhookslist endpoints + latest delivery info. - -
DELETE /webhooks/:idremove endpoint. - -
GET /webhooks/:id/deliveries?page=1&pageSize=20inspect delivery logs.
Supported event names
certificate.issued,certificate.revoked,anchor.confirmed,trust.updated
Current production triggers actively dispatch certificate lifecycle events:certificate.issuedandcertificate.revoked.
Delivery contract
- - Method:
POST - - Content-Type:
application/json - - Timeout per attempt:
10s - - Retries:
3attempts with backoff1s, 4s, 9s - - Success criteria: any HTTP
2xxresponse - - 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";
// Store and protect the raw secret returned once at webhook creation (whsec_...)
const rawSecret = process.env.NEEDINE_WEBHOOK_SECRET;
const signatureHeader = req.headers["x-needine-signature"]; // sha256=<hex>
const rawBody = requestRawBodyAsString; // do not reserialize JSON
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) # exact raw body
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. 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.