Capture SDK
The Capture SDK (react-native-zcam1-capture) takes photos and produces C2PA-signed assets bound to hardware-backed integrity signals.
Installation
npm i react-native-zcam1-capture
cd ios && pod installCore Concepts
The Capture SDK:
- Renders a native iOS camera preview via
ZCamera - Generates App Attest assertions over photo hashes
- Embeds C2PA manifests with
succinct.bindingsassertion - Returns signed photos ready for proof generation
API Reference
initCapture(settings)
Initializes device keys and attestation. Call once on app startup.
import { initCapture, CaptureInfo, Settings } from "react-native-zcam1-capture";
const settings: Settings = {
appId: "TEAM_ID.com.example.app",
production: false,
};
const captureInfo: CaptureInfo = await initCapture(settings);settings.appId- Your Team ID + Bundle IDsettings.production-falsefor development,truefor production
Returns: CaptureInfo containing:
appId- The app identifierdeviceKeyId- App Attest device key IDcontentPublicKey- Secure Enclave content keycontentKeyId- Derived content key identifierattestation- App Attest attestation blob
ZCamera
React component that renders the native camera preview.
import { useRef } from "react";
import { ZCamera, CaptureInfo } from "react-native-zcam1-capture";
function CameraScreen({ captureInfo }: { captureInfo: CaptureInfo }) {
const camera = useRef<ZCamera>(null);
return (
<ZCamera
ref={camera}
captureInfo={captureInfo}
position="back" // "front" | "back"
isActive={true} // Enable/disable camera
style={{ flex: 1 }}
/>
);
}captureInfo(required) - FrominitCapture()position- Camera to use:"front"or"back"(default:"back")isActive- Whether camera is running (default:true)style- Style for the camera view
ZCamera.takePhoto()
Captures a photo and returns a signed ZPhoto.
const photo = await camera.current?.takePhoto();
console.log(photo.originalPath); // Raw capture path
console.log(photo.path); // C2PA-signed photo pathReturns: ZPhoto with:
originalPath- Path to the raw captured imagepath- Path to the C2PA-signed image withsuccinct.bindings
Complete Example
import { useEffect, useRef, useState } from "react";
import { View, Button, Text, StyleSheet } from "react-native";
import { SafeAreaView } from "react-native-safe-area-context";
import { initCapture, ZCamera, CaptureInfo } from "react-native-zcam1-capture";
import { FileSystem, Dirs } from "react-native-file-access";
export function CaptureScreen() {
const camera = useRef<ZCamera>(null);
const [captureInfo, setCaptureInfo] = useState<CaptureInfo>();
const [lastPhoto, setLastPhoto] = useState<string>();
useEffect(() => {
const settings = {
appId: process.env.EXPO_PUBLIC_APP_ID!,
production: false,
};
initCapture(settings).then(setCaptureInfo);
}, []);
const handleCapture = async () => {
const photo = await camera.current?.takePhoto();
if (!photo) return;
// Save to app's document directory
const destPath = `${Dirs.DocumentDir}/photos/${Date.now()}.jpg`;
await FileSystem.mkdir(`${Dirs.DocumentDir}/photos`);
await FileSystem.cp(photo.path, destPath);
setLastPhoto(destPath);
};
if (!captureInfo) {
return (
<View style={styles.centered}>
<Text>Initializing camera...</Text>
</View>
);
}
return (
<SafeAreaView style={styles.container}>
<ZCamera ref={camera} captureInfo={captureInfo} style={styles.camera} />
<View style={styles.controls}>
<Button title="Capture" onPress={handleCapture} />
{lastPhoto && <Text>Saved: {lastPhoto}</Text>}
</View>
</SafeAreaView>
);
}
const styles = StyleSheet.create({
container: { flex: 1 },
camera: { flex: 1 },
controls: { padding: 16 },
centered: { flex: 1, justifyContent: "center", alignItems: "center" },
});Notes
initCapture()generates Secure Enclave keys on first call; subsequent calls load existing keys- App Attest only works on physical devices; the SDK uses mock values in simulators
- The captured photo at
photo.pathcontains a C2PA manifest withsuccinct.bindings—this is required for proof generation