API, CLI en MCP
Alles wat je in de app kunt doen, kun je ook met je code en agents: links, uploads of complete accounts indienen, wachten tot de posts zijn getagd en de resultaten bekijken. Eén contract, drie manieren om ermee te werken. Taken worden asynchroon verwerkt, schrijfacties zijn idempotent en je ziet de kosten vooraf en achteraf.
Nieuw bij Garfunkel? Bekijk hoe een post wordt geanalyseerd.
Snel aan de slag
Maak in de app een API-sleutel aan via Instellingen → Developers, stel die in als GARFUNKEL_API_KEY en kies daarna hoe je aan de slag wilt. MCP-clients kunnen ook inloggen met OAuth in plaats van een sleutel.
export GARFUNKEL_API_KEY=gma_live_…
garfunkel submit urls.txt --category sports --dry-run
garfunkel submit urls.txt --category sports --wait
garfunkel results export job_… --format jsonlAuthenticatie
Stuur Authorization: Bearer gma_live_… mee: een API-sleutel die aan je organisatie is gekoppeld, uit API-sleutels. De CLI en MCP lezen GARFUNKEL_API_KEY. Elke POST accepteert een Idempotency-Key; bij herhaling krijg je hetzelfde antwoord terug en worden er nooit dubbele kosten gerekend.
Een taak indienen
Na indienen krijg je meteen een taak-ID (202). priority is standard (goedkoper, verwerking duurt minuten tot uren) of fast. Stel dry_run: true in voor een gratis schatting met validatie per item.
curl -X POST https://garfunkel.gar-ai.com/api/v1/jobs \
-H "Authorization: Bearer $GARFUNKEL_API_KEY" \
-H "Content-Type: application/json" \
-H "Idempotency-Key: $(uuidgen)" \
-d '{
"items": [{ "url": "https://www.tiktok.com/@user/video/7412345678901234567" }],
"options": { "translate_to": "en" },
"dry_run": true
}'Itemstatussen: queued → fetching → processing → succeeded | failed | canceled.
Accounttaken
“Elke post van @handle sinds 2025-01-01.” Tellen kost 2¢ per 20 posts die nieuw zijn voor je team. Het bedrag wordt vooraf gereserveerd en teruggeboekt wanneer je de posts laat analyseren. Daarna wacht de opdracht in awaiting_confirmation, met per account posts_found, oldest_post_at, reached_since en notices (bijvoorbeeld als een platform alleen posts vanaf een latere datum teruggeeft). Bevestig met POST /jobs/{id}/confirm of stel options.max_credits in om automatisch te bevestigen.
{
"items": [
{ "account": "@nike", "platform": "tiktok", "since": "2025-01-01", "max_posts": 1000 },
{ "account": "https://x.com/nasa", "since": "2025-01-01" }
],
"options": { "max_credits": 50000 }
}Uploads
De bestanden gaan rechtstreeks naar de opslag en lopen nooit via de API. Uploads die niet binnen 24 uur aan een taak zijn gekoppeld, worden verwijderd.
POST /api/v1/uploads
{ "filename": "clip.mp4", "content_type": "video/mp4", "size_bytes": 1234567 }
→ { "id": "upl_…", "upload_url": "<presigned PUT>", "method": "PUT", "headers": {…}, "expires_at": "…" }
# PUT the bytes straight to storage, then submit { "upload_id": "upl_…" } as a job item.Resultaten
Eén geanalyseerde post. Embeddingvectoren worden alleen teruggegeven met ?include=embedding. pacing is gebaseerd op shotdetectie (bèta).
{
"item_id": "itm_01J…",
"job_id": "job_01J…",
"source": { "platform": "tiktok", "url": "…", "author": "…", "posted_at": "…",
"metrics": { "views": 0, "likes": 0, "comments": 0, "shares": 0 } },
"caption": "…",
"language": "es",
"transcript": { "text": "…", "segments": [{ "start": 0.0, "end": 2.1, "text": "…" }] },
"translation": { "language": "en", "caption": "…", "transcript": "…", "on_screen_text": "…" },
"summary": "…",
"tags": { "format": "…", "theme": "…", "tone": ["…"], "topics": ["…"], "keywords": ["…"] },
"hook": { "type": "…", "timing_s": 1.2, "confidence": 0.8 },
"pacing": { "beta": true, "shot_count": 14, "avg_shot_s": 2.1, "cuts_per_s": 0.47, "first_cut_s": 0.9 },
"embedding": { "dims": 1024 },
"credits_charged": 12,
"processed_at": "…"
}Endpoints
| Endpoint | Wat het doet |
|---|---|
| POST /api/v1/jobs | Dien URL’s, uploads of accounts in (dry_run voor een gratis schatting). |
| GET /api/v1/jobs/{id} | Status, aantallen per status, gereserveerde, in rekening gebrachte en vrijgegeven bedragen (centen), accounts en meldingen. |
| GET /api/v1/jobs/{id}/items | Items met paginering; filter met ?status=failed. |
| POST /api/v1/jobs/{id}/confirm | Reserveer het bedrag voor een accounttaak die op bevestiging wacht. |
| POST /api/v1/jobs/{id}/cancel | Annuleer items in de wachtrij; het gereserveerde bedrag gaat terug naar je saldo. |
| POST /api/v1/jobs/{id}/retry | Probeer mislukte items opnieuw (opnieuw geschat en gereserveerd). |
| POST /api/v1/uploads | Vooraf ondertekende PUT voor je eigen media. |
| GET /api/v1/results | Filter op job_id, platform, tag, q. |
| POST /api/v1/results/search | Semantisch zoeken in embeddingvectoren. |
| GET /api/v1/results/export | CSV- of JSONL-stream. |
| GET /api/v1/credits | Tegoed (centen + balance_usd), reserveringen, pakketten en beloningen bij uitgaven. |
| DELETE /api/v1/data | Verwijder alle gegevens van je organisatie. |
Fouten
Elke niet-2xx-reactie gebruikt hetzelfde formaat. Codes: unauthorized, forbidden, not_found, invalid_request, insufficient_credits, rate_limited, idempotency_conflict, counting_in_progress, internal_error.
{ "error": { "code": "insufficient_credits",
"message": "Job needs $1.80; your balance is 42¢.",
"details": { "required": 180, "balance": 42 },
"retryable": false } }Foutcodes per item zijn stabiel en er worden nooit kosten voor in rekening gebracht:
| post_not_found | De post bestaat niet (meer). |
| post_private | De post is niet openbaar. |
| unsupported_url | Dit is geen URL van een TikTok-, Instagram- of X-post. |
| media_unavailable | Het platform heeft de media niet aangeleverd. |
| media_too_large | Het bestand is te groot. |
| upload_invalid | Het geüploade bestand kon niet worden gelezen. |
| provider_error | Fout bij een externe dienst — je kunt het opnieuw proberen. |
| internal_error | Er ging iets mis bij ons — je kunt het opnieuw proberen. |
CLI
export GARFUNKEL_API_KEY=gma_live_…
garfunkel submit urls.txt --category sports --dry-run # free estimate
garfunkel submit urls.txt --category sports --wait # run it
garfunkel results export job_… --format jsonl -o results.jsonl
# Whole accounts: counting is 2¢ per 20 posts (credited back when analyzed); you confirm the analysis
garfunkel submit --accounts accounts.txt --since 2025-01-01 --max-credits 50000Exitcodes: 0 gelukt, 2 onjuist gebruik, 3 geen toegang, 4 onvoldoende tegoed, 5 afgerond met mislukte items, 6 time-out.
MCP
Externe MCP via Streamable HTTP op /api/mcp, met OAuth (voeg de URL toe in Claude, ChatGPT of Cursor en geef toestemming) of een API-sleutel. Tools: estimate_job, submit_job, create_upload, confirm_job, list_job_posts, get_job, get_team, wait_for_job, list_results, get_result, list_accounts, get_account, analyze_comments, refresh_metrics, get_comments, search_results, export_results, chat_with_data, get_credit_balance, show_post, create_checkout.
{
"mcpServers": {
"garfunkel": {
"type": "http",
"url": "https://garfunkel.gar-ai.com/api/mcp",
"headers": {
"Authorization": "Bearer gma_live_…"
}
}
}
}