UDI Lens

Quickstart

UDI Lens Connect sends every scan from the App to your URL as an HTTPS POST. All you need is an endpoint that accepts JSON and verifies a signature with your API key.

You need

  • A public HTTPS URL (port 443, a valid certificate from a public CA)
  • An iPhone user subscribed to UDI Lens Connect (you can later create an organization so colleagues share the same URL)

1. Create the endpoint

In the App, open Settings, Connect, enter your URL and tap Create. The App shows the API key (starting with whsec_) once. Copy it into your secret store right away (environment variable, Vault, Key Vault).

The API key is shown only once. If you lose it, rotate it in the App or the portal.

2. Implement the endpoint

When a request arrives:

  1. Verify webhook-signature against the raw body with your API key (see Verifying signatures)
  2. If type is endpoint.verification, reply 200 with {"challenge": "<data.challenge>"}
  3. For other events, deduplicate by webhook-id, reply 2xx, then process asynchronously

A minimal Node.js example:

import { createHmac, timingSafeEqual } from "node:crypto";

function verify(apiKey, headers, rawBody) {
  const id = headers["webhook-id"], ts = headers["webhook-timestamp"], sigs = headers["webhook-signature"];
  if (!id || !ts || !sigs || Math.abs(Date.now() / 1000 - Number(ts)) > 300) return false;
  const key = Buffer.from(apiKey.replace(/^whsec_/, ""), "base64");
  const expected = Buffer.from("v1," + createHmac("sha256", key).update(`${id}.${ts}.${rawBody}`).digest("base64"));
  return sigs.split(" ").some((s) => Buffer.from(s).length === expected.length && timingSafeEqual(Buffer.from(s), expected));
}

Python, C# and Java examples are in Verifying signatures.

3. Verify the endpoint

Back in the App, tap Verify. We send endpoint.verification; once your endpoint echoes the challenge, the endpoint becomes active.

4. Send a test event

Tap Send test event. You receive an endpoint.test with a sample scan in the same shape as scan.created.

5. Start scanning

With Auto send on, every completed scan sends a scan.created. Offline scans are kept on the iPhone and sent when the connection returns.

No endpoint yet?

Use the test receiver. It gives you a temporary URL to enter in the App, and shows each event and its signature check live.