Naar de inhoud

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 jsonl

Authenticatie

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

EndpointWat het doet
POST /api/v1/jobsDien 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}/itemsItems met paginering; filter met ?status=failed.
POST /api/v1/jobs/{id}/confirmReserveer het bedrag voor een accounttaak die op bevestiging wacht.
POST /api/v1/jobs/{id}/cancelAnnuleer items in de wachtrij; het gereserveerde bedrag gaat terug naar je saldo.
POST /api/v1/jobs/{id}/retryProbeer mislukte items opnieuw (opnieuw geschat en gereserveerd).
POST /api/v1/uploadsVooraf ondertekende PUT voor je eigen media.
GET /api/v1/resultsFilter op job_id, platform, tag, q.
POST /api/v1/results/searchSemantisch zoeken in embeddingvectoren.
GET /api/v1/results/exportCSV- of JSONL-stream.
GET /api/v1/creditsTegoed (centen + balance_usd), reserveringen, pakketten en beloningen bij uitgaven.
DELETE /api/v1/dataVerwijder 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_foundDe post bestaat niet (meer).
post_privateDe post is niet openbaar.
unsupported_urlDit is geen URL van een TikTok-, Instagram- of X-post.
media_unavailableHet platform heeft de media niet aangeleverd.
media_too_largeHet bestand is te groot.
upload_invalidHet geüploade bestand kon niet worden gelezen.
provider_errorFout bij een externe dienst — je kunt het opnieuw proberen.
internal_errorEr 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 50000

Exitcodes: 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_…"
      }
    }
  }
}