> ## Documentation Index
> Fetch the complete documentation index at: https://docs.fennec-asr.com/llms.txt
> Use this file to discover all available pages before exploring further.

# Transcribe from a URL

### Step 1: Get your API Key

Your API key is used to authenticate your requests. Follow [this link](https://app.fennec-asr.com/dashboard/api-keys) to grab your first API key.

### Step 2: Install the SDK

```python theme={null}
pip install fennec-asr
```

Let's write a simple script to send a URL to the API.

### Step 3: Transcribe!

```python theme={null}
from fennec_asr import FennecASRClient
print(FennecASRClient(api_key="YOUR_API_KEY").transcribe_url("https://upload.wikimedia.org/wikipedia/commons/3/3f/En-History_of_Corpus_Christi%2C_Texas.ogg"))
```

Don't want to use the SDK? See the example code below:

<AccordionGroup>
  <Accordion icon="language" title="Example Code">
    <CodeGroup dropdown>
      ```python quickstart.py theme={null}
        import requests
        import json
        import time

        BASE_URL = "https://api.fennec-asr.com/api/v1"
        API_KEY = "YOUR_API_KEY_HERE"
        AUDIO_URL = "https://upload.wikimedia.org/wikipedia/commons/3/3f/En-History_of_Corpus_Christi%2C_Texas.ogg"
        POLL_INTERVAL_SECONDS = 3
        MAX_WAIT_SECONDS = 300

        headers = {"Content-Type": "application/json", "X-API-Key": API_KEY}
        payload = {"audio": AUDIO_URL, "context": "testing with a python script"}

        def transcribe_audio_url():
        try:
            # 1. Submit the job
            print("Submitting transcription job...")
            submit_response = requests.post(f"{BASE_URL}/transcribe/url", headers=headers, data=json.dumps(payload))
            submit_response.raise_for_status()
            job_info = submit_response.json()
            job_id = job_info.get("job_id")
            print(f"✅ Job submitted successfully! Job ID: {job_id}\n")

            # 2. Poll for the result
            start_time = time.time()
            while time.time() - start_time < MAX_WAIT_SECONDS:
                print("Polling for status...")
                status_url = f"{BASE_URL}/transcribe/status/{job_id}"
                status_response = requests.get(status_url, headers=headers)

                if status_response.status_code == 200:
                    status_data = status_response.json()
                    job_status = status_data.get("status")
                    print(f"  Current status: '{job_status}'")

                    if job_status == "completed":
                        print("\n🎉 Transcription complete!")
                        print("Transcript:", status_data.get("transcript"))
                        break
                    elif job_status == "failed":
                        print("\n❌ Transcription failed.")
                        print("Error:", status_data.get("transcript"))  # Assuming error is stored in transcript field
                        break
                else:
                    print(f"  Error polling status: {status_response.status_code}")

                time.sleep(POLL_INTERVAL_SECONDS)
            else:
                print("\n⏰ Polling timed out.")

        except requests.exceptions.RequestException as e:
            print(f"An error occurred: {e}")

        # --- Run the script ---
        if __name__ == "__main__":
            transcribe_audio_url()
      ```

      ```ts quickstart.ts theme={null}
        #!/usr/bin/env node
        "use strict";

        const BASE = "https://api.fennec-asr.com/api/v1";
        const KEY = process.env.ASR_API_KEY;
        const AUDIO = process.argv[2] || "https://upload.wikimedia.org/wikipedia/commons/3/3f/En-History_of_Corpus_Christi%2C_Texas.ogg";
        const INTERVAL = 3000, MAX = 300000;
        const wait = (ms) => new Promise(r => setTimeout(r, ms));

        (async () => {
          if (!KEY) throw new Error("Set ASR_API_KEY");

          const submit = await fetch(`${BASE}/transcribe/url`, {
            method: "POST",
            headers: { "Content-Type": "application/json", "X-API-Key": KEY },
            body: JSON.stringify({ audio: AUDIO, context: "testing with a node script" }),
          });
          if (!submit.ok) throw new Error(`Submit ${submit.status}: ${await submit.text()}`);
          const { job_id } = await submit.json();
          if (!job_id) throw new Error("No job_id");

          const start = Date.now();
          for (;;) {
            const res = await fetch(`${BASE}/transcribe/status/${job_id}`, { headers: { "X-API-Key": KEY } });
            if (!res.ok) throw new Error(`Status ${res.status}: ${await res.text()}`);
            const s = await res.json();

            if (s.status === "completed") return void console.log(s.transcript || "");
            if (s.status === "failed") { console.error("Failed:", s.transcript || ""); process.exit(1); }
            if (Date.now() - start > MAX) { console.error("Timed out."); process.exit(1); }
            await wait(INTERVAL);
          }
        })().catch(e => { console.error(e.message || e); process.exit(1); });

      ```
    </CodeGroup>
  </Accordion>
</AccordionGroup>

## Next Steps

Now that you've completed your first transcription, you can explore the API's more powerful features.

<CardGroup cols={2}>
  <Card title="Improve Accuracy with Context" icon="brain-circuit" href="/essentials/contextual-correction">
    Provide hints and jargon to the AI to get more accurate results for specialized audio.
  </Card>

  <Card title="Automatic Formatting" icon="align-left" href="/essentials/formatting">
    Automatically add newlines and paragraphs to your transcript based on speech pauses.
  </Card>

  <Card title="Full API Reference" icon="code" href="/api-reference/create-transcription-job">
    Explore all endpoints, parameters, and schemas in detail.
  </Card>
</CardGroup>
