Skip to main content

API Integrations

The Certi-Lock® app integrates with three external APIs: Algolia for product catalog search, the Certi-Lock Image API for sealed item images, and the WordPress REST API for promotional banners and error logging.


Overview

The app queries the Algolia search index to retrieve product data when a QR/barcode is scanned. The first 4 characters of the serial number are used as a filter to locate the matching product.

Configuration

SettingEnvironment Variable
App IDEXPO_PUBLIC_ALGOLIA_APP_ID
API KeyEXPO_PUBLIC_ALGOLIA_API_KEY
Index NameEXPO_PUBLIC_ALGOLIA_INDEX_NAME

Request Format

// api/get-data.ts
const response = await fetch(
`https://${appId}-dsn.algolia.net/1/indexes/${indexName}/query`,
{
method: "POST",
headers: {
"Content-Type": "application/json",
"X-Algolia-API-Key": apiKey,
"X-Algolia-Application-Id": appId,
},
body: JSON.stringify({
params: `filters=serial_number_prefix:${serialPrefix}`,
}),
}
);

Response Processing

The Algolia response includes product details that are mapped to the local database schema:

Algolia FieldLocal DB ColumnDescription
namenameProduct display name
subtitlesubtitleProduct subtitle/description
image_urlimageUrlProduct image URL
product_detailsproductDetailsJSON object with product specifications
metal_typemetalTypeMetal type (gold, silver) for fallback image
shapeshapeShape (round, bar) for fallback image

Error Handling

  • If no results are returned, the item is saved with default/placeholder data
  • Network failures are caught and logged to Sentry and the WordPress error API
  • The serial number is always preserved regardless of API response

Certi-Lock Image API

Overview

The Image API provides high-resolution sealed images for verified precious metals items. Each image is fetched by serial number and stored locally with a SHA256 hash-based filename.

Configuration

SettingEnvironment Variable
Base URLEXPO_PUBLIC_IMAGE_API_URL
API KeyEXPO_PUBLIC_IMAGE_API_KEY

Request Format

// api/get-image.ts
const response = await fetch(
`${baseUrl}?serial_number=${serialNumber}&api_key=${apiKey}`
);

Image Processing Flow

API Response (image data)


SHA256 Hash Generation
(expo-crypto)


Save to Document Directory
(expo-file-system)


Store hash in SQLite
(imageHash column)

Step-by-step:

  1. Fetch image binary data from the Image API using the serial number
  2. Generate a SHA256 hash of the image content using expo-crypto
  3. Save the image file to the app's document directory with the hash as the filename
  4. Store the hash in the SQLite imageHash column for later retrieval
  5. On subsequent views, load the image directly from the local filesystem using the stored hash

Fallback Images

When the Image API returns no image (e.g., image still processing), the app displays a fallback based on the product's metal type and shape:

Metal TypeShapeFallback Image
GoldRoundfallback-round-gold.png
GoldBarfallback-bar-gold.png
SilverRoundfallback-round-silver.png
SilverBarfallback-bar-silver.png

The fallback selection logic is in api/get-fallback-image.ts.


WordPress REST API

The WordPress REST API serves two purposes: promotional banners for the home screen and error logging for monitoring.

Configuration

SettingEnvironment Variable
Base URLEXPO_PUBLIC_WP_API_URL
API KeyEXPO_PUBLIC_WP_API_KEY

Promotional Banners

Banners are displayed on the home screen in a carousel. They are fetched from WordPress and cached locally for 24 hours.

// api/get-banners.ts — Simplified flow
const cached = await AsyncStorage.getItem("banners_cache");
if (cached) {
const { data, timestamp } = JSON.parse(cached);
const isExpired = Date.now() - timestamp > 24 * 60 * 60 * 1000;
if (!isExpired) return data;
}

const response = await fetch(`${baseUrl}/banners`, {
headers: { "X-API-Key": apiKey },
});
const banners = await response.json();

await AsyncStorage.setItem("banners_cache", JSON.stringify({
data: banners,
timestamp: Date.now(),
}));

return banners;

Cache behavior:

ScenarioAction
Cache exists and is less than 24 hours oldReturn cached data
Cache exists but is older than 24 hoursFetch fresh data, update cache
No cache existsFetch from API, create cache
API request failsReturn cached data if available, otherwise empty array

Error Logging

Critical errors are sent to the WordPress REST API for centralized monitoring alongside server-side logs:

// api/log-error.ts
const response = await fetch(`${baseUrl}/log-error`, {
method: "POST",
headers: {
"Content-Type": "application/json",
"X-API-Key": apiKey,
},
body: JSON.stringify({
error: errorMessage,
context: additionalContext,
}),
});

This supplements Sentry error tracking by providing logs accessible from the WordPress admin dashboard.


Sentry Error Tracking

Configuration

Sentry is integrated at the Metro bundler level and initialized in the root layout:

// metro.config.js
const { getSentryExpoConfig } = require("@sentry/react-native/metro");
const config = getSentryExpoConfig(__dirname);

Runtime Configuration

SettingValue
DSNhttps://1579b939d45a6ce0dbc68f417aaf12a4@o4509243283800064.ingest.us.sentry.io/4509243290681344
Traces Sample Rate (Dev)1.0 (100%)
Traces Sample Rate (Prod)0.1 (10%)
Native Frame TrackingEnabled
Auto PerformanceEnabled

What Gets Tracked

  • Unhandled JavaScript exceptions
  • Native crashes (iOS and Android)
  • Navigation performance (screen transitions)
  • API call durations
  • Custom error events logged via Sentry.captureException()

Environment Variables Summary

All API configuration is managed through environment variables prefixed with EXPO_PUBLIC_ to make them accessible in the client-side JavaScript bundle:

# Algolia Product Search
EXPO_PUBLIC_ALGOLIA_API_KEY=<search-only-api-key>
EXPO_PUBLIC_ALGOLIA_APP_ID=<application-id>
EXPO_PUBLIC_ALGOLIA_INDEX_NAME=<index-name>

# Certi-Lock Image API
EXPO_PUBLIC_IMAGE_API_KEY=<api-key>
EXPO_PUBLIC_IMAGE_API_URL=<base-url>

# WordPress REST API
EXPO_PUBLIC_WP_API_KEY=<api-key>
EXPO_PUBLIC_WP_API_URL=<base-url>
caution

All EXPO_PUBLIC_ variables are embedded in the JavaScript bundle and visible to end users. Use read-only/search-only API keys with minimal permissions. Never expose admin or write-capable keys.