Spaces:
Runtime error
Vault - API Contracts
Generated: 2026-02-11
Framework: Next.js 15 App Router
API Overview
Vault uses Next.js 15 App Router with two primary patterns:
- API Routes - Traditional REST endpoints (
src/app/api/) - Server Actions - Form mutations with progressive enhancement (
'use server')
API Routes
Authentication
POST /api/auth/[...all]
Better Auth handler for all authentication endpoints.
Handled by: src/app/api/auth/[...all]/route.ts
Endpoints:
POST /api/auth/sign-in/email- Email/password sign inPOST /api/auth/sign-up/email- Email/password registrationGET /api/auth/session- Get current sessionPOST /api/auth/sign-out- Sign outGET /api/auth/callback/google- Google OAuth callback
Inngest
POST /api/inngest
Inngest webhook handler for background job execution.
Handled by: src/app/api/inngest/route.ts
Registered Functions:
scan-video-archive- YouTube archive scanningdetect-objects- AI object detectionmatch-marketplace- Marketplace product matchingmonitor-link-health- Link health monitoringcheckSingleLinkHealth- Single link checkwarmFeaturedCreatorsCache- Cache warminghealSocialMetadata- Social metadata repair
Authentication: Requires INNGEST_SIGNING_KEY in production.
YouTube Integration
GET /api/youtube/connect
Initiates YouTube OAuth flow.
Handled by: src/app/api/youtube/connect/route.ts
Response: Redirects to Google OAuth consent screen.
GET /api/youtube/callback
Handles YouTube OAuth callback.
Handled by: src/app/api/youtube/callback/route.ts
Query Parameters:
code- OAuth authorization codestate- CSRF state token
Response: Redirects to dashboard with connection status.
POST /api/youtube/disconnect
Disconnects YouTube channel.
Handled by: src/app/api/youtube/disconnect/route.ts
Response: JSON with success status.
Health Check
GET /api/health
Health check endpoint for monitoring.
Handled by: src/app/api/health/route.ts
Response:
{
"status": "ok",
"timestamp": "2026-02-11T20:00:00.000Z"
}
Manual Triggers (Development)
POST /api/manual-trigger
Manually trigger Inngest functions (development only).
Handled by: src/app/api/manual-trigger/route.ts
Server Actions
Server Actions are defined with 'use server' directive and called directly from client components.
Discovery Actions
connectYouTubeAction()
Initiates YouTube connection flow.
File: src/features/discovery/actions/connect-youtube.ts
Returns:
{
success: boolean;
error?: string;
}
Vault Actions
redirectToMarketplace(matchId, viewerIp, userAgent, referrer)
Tracks and redirects to marketplace affiliate link.
File: src/features/vault/actions/redirect-to-marketplace.ts
Parameters:
matchId: string- Marketplace match IDviewerIp?: string- Anonymized viewer IPuserAgent?: string- Client user agentreferrer?: string- Referrer URL
Returns:
{
success: boolean;
url?: string;
error?: string;
}
searchProducts(query, creatorSlug)
Search products across creator's vault.
File: src/features/vault/actions/search-products.ts
Parameters:
query: string- Search querycreatorSlug: string- Creator's URL slug
Returns:
{
success: boolean;
products?: ProductCard[];
error?: string;
}
triggerAnalysis(videoId, videoUrl)
Trigger AI analysis for a video.
File: src/features/vault/actions/trigger-analysis.ts
Parameters:
videoId: string- Internal video IDvideoUrl: string- Video URL for processing
Returns:
{
success: boolean;
error?: string;
}
quickAnalyze(videoUrl)
Quick analysis tool for arbitrary video URLs.
File: src/features/vault/actions/quick-analyze.ts
Moderation Actions
approveDetection(detectionId)
Approve a detected object for vault display.
File: src/features/moderation/actions/approve-detection.ts
Parameters:
detectionId: string- Detection ID
Returns:
{
success: boolean;
error?: string;
}
rejectDetection(detectionId)
Reject a detected object.
File: src/features/moderation/actions/reject-detection.ts
Parameters:
detectionId: string- Detection ID
Returns:
{
success: boolean;
error?: string;
}
bulkApprove(detectionIds)
Approve multiple detections at once.
File: src/features/moderation/actions/bulk-approve.ts
Parameters:
detectionIds: string[]- Array of detection IDs
Returns:
{
success: boolean;
approved: number;
failed: number;
error?: string;
}
bulkReject(detectionIds)
Reject multiple detections at once.
File: src/features/moderation/actions/bulk-reject.ts
editDetection(detectionId, updates)
Edit detection details (name, category, thumbnail).
File: src/features/moderation/actions/edit-detection.ts
Parameters:
detectionId: string- Detection IDupdates: { objectName?, category?, thumbnailUrl? }- Fields to update
Returns:
{
success: boolean;
error?: string;
}
deleteDetection(detectionId)
Permanently delete a detection.
File: src/features/moderation/actions/delete-detection.ts
addDetection(videoId, data)
Manually add a product detection to a video.
File: src/features/moderation/actions/add-detection.ts
Parameters:
videoId: string- Video IDdata: { objectName, category, frameTimestamp?, thumbnailUrl?, marketplaceMatches? }
Admin Moderation Actions
adminCorrectDetection(detectionId, corrections)
Admin correction with audit trail.
File: src/features/moderation/actions/admin-correct-detection.ts
Parameters:
detectionId: string- Detection IDcorrections: { objectName?, category? }- Corrected values
Returns:
{
success: boolean;
error?: string;
}
adminMarkIncorrect(detectionId, reasonCode)
Mark detection as incorrect with reason.
File: src/features/moderation/actions/admin-mark-incorrect.ts
Parameters:
detectionId: string- Detection IDreasonCode: 'wrong_object' | 'wrong_category' | 'false_positive' | 'unclear_image' | 'duplicate' | 'out_of_scope'
Marketplace Actions
triggerMarketplaceMatch(objectId)
Trigger marketplace matching for a detection.
File: src/features/marketplace/actions/trigger-marketplace-match.ts
Parameters:
objectId: string- Detection ID
Returns:
{
success: boolean;
matchCount?: number;
error?: string;
}
triggerLinkHealthCheck(matchId)
Check health of a specific affiliate link.
File: src/features/marketplace/actions/trigger-link-health-check.ts
Interest Actions
createInterestPledge(marketplaceMatchId, email, detectedObjectId)
Create an interest pledge for out-of-stock item.
File: src/features/interest/actions/create-interest-pledge.ts
Parameters:
marketplaceMatchId: string | null- Match IDemail: string- User emaildetectedObjectId: string | null- Detection ID
Returns:
{
success: boolean;
isDuplicate?: boolean;
error?: string;
}
Request & Proposal Actions
submitRequest(videoId, data)
Submit a product request for a video.
File: src/actions/submit-request.ts
Parameters:
videoId: string- Video IDdata: { viewerName?, viewerEmail?, note, imageUrl?, frameTimestamp? }
submitProposal(videoId, data)
Submit an affiliate link proposal.
File: src/actions/submit-proposal.ts
Parameters:
videoId: string- Video IDdata: { productUrl, affiliateUrl, productName, price?, imageUrl?, note?, objectId? }
handleProposal(proposalId, action)
Approve or reject a proposal.
File: src/features/moderation/actions/handle-proposal.ts
Parameters:
proposalId: string- Proposal IDaction: 'approve' | 'reject'- Action to take
Claim Actions
claimVideo(videoId, creatorId)
Claim ownership of a video.
File: src/actions/claim-video.ts
Data Fetching Patterns
Server-Side Rendering (SSR)
Pages fetch data directly in async server components:
// src/app/vault/[creatorSlug]/page.tsx
export default async function VaultPage({ params }) {
const vault = await VaultService.getCreatorVault(params.creatorSlug);
return <VaultGrid vault={vault} />;
}
Incremental Static Regeneration (ISR)
Pages can use ISR for caching:
export const revalidate = 300; // 5 minutes
Client-Side Fetching
Client components use SWR or direct server action calls:
// Using server action
const result = await approveDetection(detectionId);
if (result.success) {
toast.success('Detection approved');
}
Error Handling
All server actions follow a consistent error pattern:
{
success: boolean;
error?: string;
// Additional fields as needed
}
Errors are captured with Sentry:
import * as Sentry from '@sentry/nextjs';
catch (error) {
Sentry.captureException(error, {
tags: { action: 'action-name', resource_id: id },
});
return { success: false, error: 'Failed to perform action' };
}
Authentication & Authorization
Session Access
import { auth } from '@/lib/auth';
import { headers } from 'next/headers';
const session = await auth.api.getSession({
headers: await headers(),
});
Authorization Pattern
// Verify ownership
const detection = await db.query.detectedObjects.findFirst({
where: eq(detectedObjects.id, detectionId),
});
if (detection.creatorId !== session.user.id) {
return { success: false, error: 'Unauthorized' };
}
Admin Check
const adminEmails = process.env.ADMIN_EMAILS?.split(',') || [];
const isAdmin = session.user.email && adminEmails.includes(session.user.email);
Related Documentation
- Data Models - Database schema
- Inngest Workflows - Background jobs
- Development Guide - Setup instructions