GoIdentity API Integration

Create verification checks from websites, CRM platforms, SAP workflows, or other backend systems without opening the GoIdentity dashboard.

Partner APIServer-to-serverVersion v1Last updated July 2026

Overview

Use the integration API when your own platform needs to initiate identity verification checks programmatically. The API uses the verification services and questionnaire configured on the SDK integration in GoIdentity; request payloads cannot override paid checks.

CapabilityEndpoint or feature
Create a verificationPOST /integrations/v1/verifications
Poll current statusGET /integrations/v1/verifications/:id/status
Retrieve a single verificationGET /integrations/v1/verifications/:id
List verificationsGET /integrations/v1/verifications?limit&page
Receive completed outcomesverification.completed webhook
Use the Public SDK when the customer should complete a browser-embedded form. Use this API when your backend owns the initiation workflow. Both share the same integration credentials and configuration.

Before You Start

Gather all of the following first — most integration friction comes from a missing credential, an unconfigured service, or an empty balance.

RequirementPurpose
GoIdentity dashboard accountCreate integrations, configure services, view results.
Client key + secret (gidck_…, gidcs_…)Server-to-server credentials sent on every request. Never expose the secret in a browser or client app.
Verification services configured on the integrationWhich checks run (ID + face, sanctions/PEP, location, questionnaire). Enforced server-side; requests cannot change them.
Sufficient organisation balanceChecks are billed. An empty balance returns INSUFFICIENT_BALANCE (402).
Webhook endpoint (HTTPS) + signing secretRecommended. Receive completion events instead of polling. Configure the URL and generate the secret in the dashboard.
Sandbox / dev credentialsRun integration smoke tests before going live.

Architecture

Your backend initiates a check; the applicant completes it in the GoIdentity mobile app; GoIdentity runs the verification pipeline asynchronously and notifies you when it finishes.

Your backend
  -> POST /integrations/v1/verifications        (create the check)
  -> GoIdentity emails the applicant an invite / one-time code
  -> applicant completes the checks in the GoIdentity mobile app
     (document capture, face match, location, questionnaire, ...)
  -> GoIdentity runs the verification pipeline   (asynchronous)
  -> the verification reaches a terminal status
  -> GoIdentity POSTs a signed "verification.completed" webhook
  -> (optional) you can GET /verifications/:id/status at any time

What runs where

  • Your backend: stores the client key + secret, creates verifications, and hosts the webhook endpoint that receives outcomes.
  • GoIdentity API:authenticates the credentials, applies the integration’s configured services, creates the check, and delivers the signed webhook.
  • GoIdentity mobile app + pipeline: where the applicant captures their document and face, and where the asynchronous verification actually happens.
A created verification is not instant. It starts as New and only becomes a terminal status after the applicant completes the mobile flow and the pipeline finishes. Design for asynchronous completion — rely on the webhook, not a synchronous response.

Quickstart

  1. Create an SDK integration in the dashboard (one integration powers the SDK, the API, and webhooks).
  2. Configure the verification services and optional questionnaire on it — these are enforced on every API request.
  3. Copy the client key (gidck_…) and client secret (gidcs_…); store the secret in your backend secrets manager.
  4. Top up the organisation balance so checks can be created.
  5. (Recommended) Set a webhook URL, generate a signing secret, and choose whether to include KYC data / the PDF report.
  6. Create a verification with POST /integrations/v1/verifications.
  7. Receive the verification.completed webhook (or poll the status endpoint).
  8. Verify the webhook signature, dedupe on the event id, and persist the outcome against your externalReference.
  9. Smoke-test in sandbox, then switch to production credentials and URLs.

Authentication

Every request must include the client key and client secret generated for the active SDK integration. Credentials are scoped to the owning organisation and all created checks are traceable to that integration. There is no token-exchange step — send both headers on every request.

X-GoIdentity-Client-Key: gidck_CLIENT_KEY_ID
X-GoIdentity-Client-Secret: gidcs_CLIENT_SECRET
Content-Type: application/json
  • Store gidcs_ secrets only in backend secrets storage.
  • Rotate secrets from the GoIdentity dashboard if they are exposed.
  • Disabled integrations cannot create or retrieve verification checks (INTEGRATION_DISABLED, 403).

Create Verification

Create a verification from core customer details. The optional externalReference should be your stable CRM, order, or user identifier for reconciliation.

FieldRequiredNotes
externalReferenceNoUp to 200 characters. Echoed back in status and webhooks.
fullNameYesCustomer legal name.
dateOfBirthYesISO date (YYYY-MM-DD), must be in the past.
emailYesUsed for the verification record and dashboard traceability.
contactNumberYesPrefer E.164 format with country code.
countryCodeNoISO 3166-1 alpha-2 where available.
POST https://api.dev.goidentity.com/integrations/v1/verifications
X-GoIdentity-Client-Key: gidck_CLIENT_KEY_ID
X-GoIdentity-Client-Secret: gidcs_CLIENT_SECRET
Idempotency-Key: order-12345
Content-Type: application/json

{
  "externalReference": "crm-contact-12345",
  "fullName": "Jane Doe",
  "dateOfBirth": "1990-04-12",
  "email": "jane@example.com",
  "contactNumber": "+447700900123",
  "countryCode": "GB"
}
HTTP/1.1 201 Created

{
  "verificationId": "9c0f38d4-8f12-48e7-a762-7710939d7c55",
  "externalReference": "crm-contact-12345",
  "status": "New",
  "createdOn": "2026-06-18T11:30:00Z",
  "statusUrl": "/integrations/v1/verifications/9c0f38d4-8f12-48e7-a762-7710939d7c55/status"
}
Send an optional Idempotency-Key header to make retries safe: repeating a create with the same key for the same integration returns the original verification instead of creating a duplicate or charging the balance twice.

Lifecycle & Status

A verification moves through a non-terminal phase while the applicant completes their checks, then settles on exactly one terminal status.

StatusTerminal?Meaning
NewNoCreated; the applicant has not started yet.
InProgressNoThe applicant is completing checks / the pipeline is running.
PassYesVerification succeeded.
FailYesVerification failed.
ReviewRequiredYesNeeds manual review before an outcome is trusted.
AdvisoryYesCompleted with advisory notes to consider.
CancelledYesThe check was cancelled and will not complete.
The verification.completed webhook fires once, when the check first reaches any terminal status.

Status Polling

Poll the status endpoint when your platform needs the latest known state. Access is restricted to checks created by the authenticated integration and organisation. Prefer webhooks; if you poll, back off and stop once the status is terminal.

GET https://api.dev.goidentity.com/integrations/v1/verifications/9c0f38d4-8f12-48e7-a762-7710939d7c55/status
X-GoIdentity-Client-Key: gidck_CLIENT_KEY_ID
X-GoIdentity-Client-Secret: gidcs_CLIENT_SECRET
HTTP/1.1 200 OK

{
  "verificationId": "9c0f38d4-8f12-48e7-a762-7710939d7c55",
  "externalReference": "crm-contact-12345",
  "status": "Pass",
  "resultReason": "Identity checks completed successfully.",
  "createdOn": "2026-06-18T11:30:00Z",
  "updatedOn": "2026-06-18T11:42:10Z",
  "completedOn": "2026-06-18T11:42:10Z",
  "fullName": "Jane Doe",
  "dateOfBirth": "1990-04-12",
  "email": "jane@example.com",
  "contactNumber": "+447700900123",
  "countryCode": "GB",
  "includeVerifications": ["id", "location", "pep"]
}

Webhooks

Webhooks are configured per SDK integration. GoIdentity sends one verification.completed event when a partner-created verification first reaches a terminal status.

SettingPurpose
WebhookUrlHTTPS endpoint that receives completion events.
WebhookEnabledControls delivery for the integration.
WebhookIncludeKycDataIncludes the applicant fields in a kycData object.
WebhookIncludePdfIncludes a base64 PDF report in a pdfReport object.
{
  "eventId": "evt_5cf17e5d0dfd4cf88950dd0e1cebf00a",
  "eventType": "verification.completed",
  "createdOn": "2026-06-18T11:42:11Z",
  "verification": {
    "verificationId": "9c0f38d4-8f12-48e7-a762-7710939d7c55",
    "externalReference": "crm-contact-12345",
    "status": "Pass",
    "resultReason": "Identity checks completed successfully.",
    "createdOn": "2026-06-18T11:30:00Z",
    "updatedOn": "2026-06-18T11:42:10Z",
    "completedOn": "2026-06-18T11:42:10Z"
  },
  "kycData": {
    "fullName": "Jane Doe",
    "dateOfBirth": "1990-04-12",
    "email": "jane@example.com",
    "contactNumber": "+447700900123",
    "countryCode": "GB",
    "includeVerifications": ["id", "location", "pep"]
  },
  "pdfReport": {
    "fileName": "KYC verification report - 9c0f38d4-8f12-48e7-a762-7710939d7c55.pdf",
    "contentType": "application/pdf",
    "contentBase64": "JVBERi0xLjQK..."
  }
}

Retry Behaviour

Any non-2xx response or network timeout is retried with exponential backoff (up to 5 attempts). Delivery attempts, response status, response body, and error messages are retained for traceability and visible in the dashboard delivery log. Acknowledge fast with a 2xx and process asynchronously.

Attempt 1: immediate
Attempt 2: about 1 minute later
Attempt 3: about 2 minutes later
Attempt 4: about 4 minutes later
Attempt 5: about 8 minutes later

Signature Verification

GoIdentity signs the raw request body with HMAC-SHA256. Verify the signature before trusting or storing webhook data.

HeaderValue
X-GoIdentity-Event-IdUnique event id. Store it for idempotency.
X-GoIdentity-TimestampUnix timestamp used in the signed payload.
X-GoIdentity-Signaturesha256=<hex digest>
import crypto from "node:crypto";

function verifyGoIdentitySignature({ secret, timestamp, body, signature }) {
  const expected =
    "sha256=" +
    crypto
      .createHmac("sha256", secret)
      .update(timestamp + "." + body)
      .digest("hex");

  return crypto.timingSafeEqual(
    Buffer.from(expected),
    Buffer.from(signature),
  );
}
Build the signed string as timestamp + "." + rawBody. Use the raw request body (not a re-serialized object), reject old timestamps, and compare signatures with a constant-time function.

Code Examples

Create a verification

curl -X POST https://api.dev.goidentity.com/integrations/v1/verifications \
  -H "X-GoIdentity-Client-Key: gidck_CLIENT_KEY_ID" \
  -H "X-GoIdentity-Client-Secret: gidcs_CLIENT_SECRET" \
  -H "Idempotency-Key: order-12345" \
  -H "Content-Type: application/json" \
  -d '{
    "externalReference": "crm-contact-12345",
    "fullName": "Jane Doe",
    "dateOfBirth": "1990-04-12",
    "email": "jane@example.com",
    "contactNumber": "+447700900123",
    "countryCode": "GB"
  }'

Poll status

// Node — poll status (prefer webhooks; poll only as a fallback)
async function getStatus(verificationId) {
  const res = await fetch(
    `https://api.dev.goidentity.com/integrations/v1/verifications/${verificationId}/status`,
    {
      headers: {
        "X-GoIdentity-Client-Key": process.env.GOIDENTITY_CLIENT_KEY,
        "X-GoIdentity-Client-Secret": process.env.GOIDENTITY_CLIENT_SECRET,
      },
    },
  );
  const check = await res.json();
  // New | InProgress | Pass | Fail | ReviewRequired | Advisory | Cancelled
  return check.status;
}

// Back off between polls (e.g. every 30s) and stop once the status is terminal.

Receive & verify a webhook

// Node / Express — receive and verify a webhook
import express from "express";
import crypto from "node:crypto";

const app = express();

app.post(
  "/webhooks/goidentity",
  // Capture the RAW body — the signature is computed over the exact bytes.
  express.raw({ type: "application/json" }),
  (req, res) => {
    const signature = req.header("X-GoIdentity-Signature") ?? "";
    const timestamp = req.header("X-GoIdentity-Timestamp") ?? "";
    const eventId = req.header("X-GoIdentity-Event-Id") ?? "";
    const rawBody = req.body.toString("utf8");

    const expected =
      "sha256=" +
      crypto
        .createHmac("sha256", process.env.GOIDENTITY_WEBHOOK_SECRET)
        .update(timestamp + "." + rawBody)
        .digest("hex");

    const valid =
      signature.length === expected.length &&
      crypto.timingSafeEqual(Buffer.from(signature), Buffer.from(expected));
    if (!valid) return res.status(400).send("bad signature");

    // Replay protection: reject deliveries with an old timestamp.
    if (Math.abs(Date.now() / 1000 - Number(timestamp)) > 300)
      return res.status(400).send("stale timestamp");

    const event = JSON.parse(rawBody);
    // Idempotency: skip an eventId you have already processed, then handle it.
    // await onceByEventId(eventId, () => persist(event.verification));

    res.sendStatus(200); // ACK fast; do heavy work asynchronously.
  },
);

Environments

Use development credentials against development endpoints and production credentials against production endpoints. Do not mix environments — you will just see INVALID_CLIENT_CREDENTIALS.
EnvironmentAPI base URLUse for
Sandbox / Devhttps://api.dev.goidentity.comIntegration testing with development credentials.
Productionhttps://api.goidentity.comLive checks with production credentials.

Troubleshooting

ProblemLikely causeFix
401 INVALID_CLIENT_CREDENTIALSWrong key/secret, or mixing dev and prod credentials.Check both headers and confirm you are calling the matching environment base URL.
403 INTEGRATION_DISABLEDThe integration is disabled in the dashboard.Re-enable the SDK integration and retry.
402 INSUFFICIENT_BALANCEThe organisation balance cannot cover the check.Top up the balance, then create the verification again.
400 VALIDATION_FAILEDA field is missing or invalid.Read the details map and correct the named fields.
Verification stays in New / InProgressThe applicant has not finished the mobile flow yet — this is expected.Wait for the webhook; the status settles once the pipeline completes.
Webhook never arrivesWebhooks disabled, non-HTTPS URL, or your endpoint is not returning 2xx.Enable webhooks, use an HTTPS URL, and check the delivery log in the dashboard for the response we received.
Signature does not matchVerifying against a re-serialized body, the wrong secret, or the wrong signed string.Use the raw body and sign timestamp + "." + rawBody with the current secret.
Duplicate webhook deliveriesYour endpoint returned a non-2xx, so delivery was retried.Return 2xx quickly and dedupe on X-GoIdentity-Event-Id.

Error Reference

API errors use a consistent JSON shape with an actionable code, message, and optional field details.

HTTP/1.1 400 Bad Request

{
  "code": "VALIDATION_FAILED",
  "message": "The verification request is invalid.",
  "details": {
    "fullName": "fullName is required.",
    "dateOfBirth": "dateOfBirth must be in the past."
  }
}
CodeHTTPAction
INVALID_CLIENT_CREDENTIALS401Check the client key and secret for the environment.
INTEGRATION_DISABLED403Enable the SDK integration in the dashboard.
VALIDATION_FAILED400Correct the request fields shown in details.
VERIFICATION_NOT_FOUND404Confirm the verification id belongs to this integration.
INSUFFICIENT_BALANCE402Top up the organisation balance before retrying.

Security

  • Keep client secrets and webhook secrets out of frontend code.
  • Use HTTPS webhook URLs only.
  • Verify webhook signatures using the raw request body.
  • Store event ids and process webhooks idempotently.
  • Log verification ids and external references, not raw PII.
  • Use separate credentials for sandbox and production.
  • Rotate credentials immediately after suspected exposure.

Go Live Checklist

  • Production client key and secret stored in a secrets manager (never client-side).
  • Organisation balance funded so checks are not blocked.
  • Verification services and questionnaire configured on the production integration.
  • Webhook URL is HTTPS and reachable from the public internet.
  • Webhook signing secret generated and stored; signature verified over the raw body.
  • Event-id idempotency implemented so retries are not double-processed.
  • All documented error codes handled (400, 401, 402, 403, 404).
  • externalReference set on every create for reconciliation.
  • Base URL switched to https://api.goidentity.com with production credentials.
  • Monitoring/alerting on webhook delivery failures via the dashboard delivery log.