3.7 KiB
3.7 KiB
Serverless API Specification
Security: All endpoints require HTTPS. Server stores OpenAI, Whisper, and LinkedIn credentials in env vars. Authenticate client requests with a signed JWT or session token.
Base URL: https://api.example.com (replace with your domain)
Endpoints
1) GET /api/auth/linkedin/start
- Purpose: Begin OAuth flow — redirect user to LinkedIn authorization URL.
- Query:
redirect_afteroptional. - Response: 302 Redirect to LinkedIn authorize URL.
- Notes: generate & store
stateto validate callback.
2) GET /api/auth/linkedin/callback
- Purpose: Receive LinkedIn code, exchange for access token, fetch user urn.
- Query:
code,state. - Response: 200 { success: true, urn: "urn:li:person:..." }
- Server actions: exchange code for token, optionally fetch
mefor urn, store token encrypted.
3) POST /api/signed-upload
- Purpose: Return signed URL to upload audio object to object store.
- Auth: JWT required.
- Request body:
{ "filename": "entry-2025-10-06-01.m4a", "contentType": "audio/m4a", "length": 345678 }
- Response:
{ "uploadUrl": "https://store.example/obj...", "objectKey": "uploads/abc.m4a", "expiresAt": "..." }
4) POST /api/transcribe/start
- Purpose: Start transcription job for uploaded audio.
- Auth: JWT required.
- Request body:
{ "objectKey":"uploads/abc.m4a", "entryId":"local-123", "anonymize":true, "language":"en" }
- Response:
{ "jobId":"trans-20251006-001", "status":"started" }
- Server action: enqueue worker to download object & call Whisper.
5) POST /api/transcribe/callback (internal)
- Purpose: Worker posts transcription result.
- Auth: internal secret.
- Request body:
{ "jobId":"trans-20251006-001", "transcriptText":"...", "confidence":0.97 }
- Response: 200 OK
- Server action: store transcript, set job DONE, notify client.
6) POST /api/generate-post
- Purpose: Proxy to OpenAI to generate post variants.
- Auth: JWT required.
- Request body:
{ "entryId":"local-123", "sanitizedText":"...", "tone":"professional", "maxChars":300, "variants":2 }
- Response:
{ "requestId":"gen-abc", "variants":[ {"id":"v1","text":"...","hashtags":["#Product"]}, ... ], "tokenUsage":{...} }
- Failure modes: 429 rate-limit, 4xx invalid request, 5xx server error.
7) POST /api/publish-linkedin
- Purpose: Publish a variant to LinkedIn via UGC API.
- Auth: JWT required. Server must check stored LinkedIn token for user.
- Request body:
{ "entryId":"local-123", "variantId":"v1", "text":"...", "visibility":"PUBLIC" }
- Response:
{ "publishId":"urn:li:ugcPost:123456" }
- Server actions: call LinkedIn
ugcPostsendpoint with author urn and content.
8) GET /api/usage
- Purpose: Return token & transcription usage to client/admin.
- Auth: admin or owner.
- Response: JSON with counters for month-to-date usage, quotas.
Notes on failure modes
- Transcription delays: return jobId and implement polling or push notifications.
- 429 from OpenAI or LinkedIn: surface friendly message and implement exponential backoff server-side.
- Authentication errors: return 401 with remediation steps (re-auth).
Environment variables (server)
- OPENAI_API_KEY
- WHISPER_API_KEY (if separate) or reuse OpenAI key
- LINKEDIN_CLIENT_ID
- LINKEDIN_CLIENT_SECRET
- STORAGE_* (S3-compatible credentials)
- JWT_SIGNING_KEY
- INTERNAL_SECRET (for callbacks)
Security & privacy
- Delete raw audio from object storage immediately after successful transcript (TTL <= 1 hour).
- Store only minimal logs (jobId, entryId, userId, timestamp, consent flag).
- Ensure TLS and server-side at-rest encryption for any stored transcripts if user opted in to cloud sync.
Copy this file into your engineering repo as docs/SERVERLESS-API-SPEC.md.