Przejdź do treści

API, CLI i MCP

Wszystko, co możesz zrobić w aplikacji, możesz też zrobić za pomocą swojego kodu i agentów: przesyłać linki, pliki lub całe konta, czekać na oznaczenie postów i sprawdzać wyniki. Jeden interfejs, trzy sposoby dostępu. Zadania są przetwarzane asynchronicznie, zapisy są idempotentne, a koszt widzisz przed rozpoczęciem i po zakończeniu.

Pierwszy raz na Garfunkel? Zobacz, jak analizujemy post.

Szybki start

Utwórz klucz API w aplikacji w sekcji Ustawienia → Deweloperzy i ustaw go jako GARFUNKEL_API_KEY. Następnie wybierz sposób dostępu. Klienci MCP mogą też zalogować się przez OAuth zamiast używać klucza.

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

Uwierzytelnianie

Wysyłaj Authorization: Bearer gma_live_… — klucz API przypisany do organizacji, który znajdziesz w sekcji Klucze API. CLI i MCP korzystają ze zmiennej GARFUNKEL_API_KEY. Każde żądanie POST przyjmuje Idempotency-Key; ponowne wysłanie tego samego żądania zwraca pierwotną odpowiedź i nie powoduje podwójnej opłaty.

Przesyłanie zadań

Po przesłaniu od razu otrzymasz identyfikator zadania (202). priority może mieć wartość standard (taniej, od kilku minut do kilku godzin) lub fast. Ustaw dry_run: true, aby bezpłatnie oszacować koszt i sprawdzić poprawność każdego elementu.

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
  }'

Statusy elementów: queued → fetching → processing → succeeded | failed | canceled.

Zadania dla kont

„Każdy post z konta @handle od 2025-01-01”. Zliczanie kosztuje 2¢ za każde 20 postów, których twój zespół jeszcze nie zliczył. Kwota jest pobierana z góry i zwracana w miarę analizowania postów. Następnie zadanie czeka w awaiting_confirmation, a dla każdego konta wyświetla posts_found, oldest_post_at, reached_since i notices (np. gdy platforma udostępnia posty tylko od późniejszej daty). Potwierdź za pomocą POST /jobs/{id}/confirm lub ustaw options.max_credits, aby potwierdzać automatycznie.

{
  "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 }
}

Przesyłanie plików

Pliki trafiają bezpośrednio do magazynu danych i nie przechodzą przez API. Pliki, których nie dołączysz do zadania w ciągu 24 godzin, zostaną usunięte.

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.

Wyniki

Jeden przeanalizowany post. Wektory osadzeń są zwracane tylko wtedy, gdy podasz ?include=embedding. pacing pochodzi z wykrywania ujęć (beta).

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

Punkty końcowe

Punkt końcowyDziałanie
POST /api/v1/jobsPrześlij adresy URL, pliki lub konta (dry_run, aby bezpłatnie oszacować koszt).
GET /api/v1/jobs/{id}Status, liczba elementów w każdym statusie, kwoty (w centach) zarezerwowane, pobrane i zwrócone, konta oraz powiadomienia.
GET /api/v1/jobs/{id}/itemsStronicowana lista elementów; filtruj za pomocą ?status=failed.
POST /api/v1/jobs/{id}/confirmZarezerwuj kwotę za zadanie dla konta oczekujące na potwierdzenie.
POST /api/v1/jobs/{id}/cancelAnuluj elementy w kolejce; zarezerwowana kwota wróci do salda.
POST /api/v1/jobs/{id}/retryPonów próbę dla elementów, których przetwarzanie się nie powiodło (ponowne oszacowanie kosztu i rezerwacja kwoty).
POST /api/v1/uploadsWygeneruj podpisany adres PUT do przesłania własnych plików multimedialnych.
GET /api/v1/resultsFiltruj za pomocą job_id, platform, tag, q.
POST /api/v1/results/searchWyszukiwanie semantyczne na podstawie wektorów osadzeń.
GET /api/v1/results/exportEksport strumieniowy w formacie CSV lub JSONL.
GET /api/v1/creditsSaldo (w centach i balance_usd), zarezerwowane środki, pakiety i nagrody za wydatki.
DELETE /api/v1/dataUsuń wszystkie dane swojej organizacji.

Błędy

Każda odpowiedź z kodem innym niż 2xx ma ten sam format. Kody: 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 } }

Kody błędów dla poszczególnych elementów są stałe i nie wiążą się z opłatą:

post_not_foundTen post już nie istnieje.
post_privateTen post nie jest publiczny.
unsupported_urlTo nie jest link do posta na TikToku, Instagramie ani X.
media_unavailablePlatforma nie zwróciła materiału.
media_too_largePlik przekracza dozwolony rozmiar.
upload_invalidNie udało się odczytać przesłanego pliku.
provider_errorBłąd po stronie dostawcy — możesz ponowić próbę.
internal_errorWystąpił błąd po naszej stronie — możesz ponowić próbę.

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

Kody wyjścia: 0 powodzenie, 2 nieprawidłowe użycie, 3 błąd uwierzytelniania, 4 za mało środków, 5 zakończono z błędami dla części elementów, 6 przekroczono limit czasu.

MCP

Zdalny MCP przez Streamable HTTP pod adresem /api/mcp, z OAuth (dodaj URL w Claude, ChatGPT lub Cursor i zatwierdź) albo kluczem API. Narzędzia: 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_…"
      }
    }
  }
}