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

# Confirm Upload

> Confirm a direct file upload and start transcription

<Warning>
  This API is not generally available. Whitelisting is currently closed.
</Warning>

## Overview

The `confirmUpload` mutation confirms that a file has been successfully uploaded to the pre-signed URL and triggers the transcription process. This is the second step in the direct upload flow.

**Upload Flow:**

1. Call [createUploadUrl](/graphql-api/mutation/create-upload-url) to get a pre-signed upload URL
2. Upload your file directly to the URL using an HTTP PUT request
3. Call `confirmUpload` to confirm the upload and start transcription

## Arguments

<ParamField path="input" type="ConfirmUploadInput" required>
  <Expandable>
    <ResponseField name="meeting_id" type="String" required>
      The meeting ID returned from the `createUploadUrl` mutation. This identifies which upload session to confirm.
    </ResponseField>
  </Expandable>
</ParamField>

## Response

<ResponseField name="success" type="Boolean">
  Indicates whether the confirmation was successful and transcription has been queued.
</ResponseField>

<ResponseField name="meeting_id" type="String">
  The meeting ID for the confirmed upload.
</ResponseField>

<ResponseField name="message" type="String">
  A message describing the result of the confirmation.
</ResponseField>

## Usage Example

```graphql theme={null}
mutation confirmUpload($input: ConfirmUploadInput!) {
  confirmUpload(input: $input) {
    success
    meeting_id
    message
  }
}
```

<RequestExample>
  ```bash curl theme={null}
  curl -X POST \
    -H "Content-Type: application/json" \
    -H "Authorization: Bearer your_api_key" \
    -d '{
      "query": "mutation($input: ConfirmUploadInput!) { confirmUpload(input: $input) { success meeting_id message } }",
      "variables": {
        "input": {
          "meeting_id": "abc123def456"
        }
      }
    }' \
    https://api.fireflies.ai/graphql
  ```

  ```javascript javascript theme={null}
  const axios = require('axios');

  const url = 'https://api.fireflies.ai/graphql';
  const headers = {
    'Content-Type': 'application/json',
    Authorization: 'Bearer your_api_key'
  };

  const input = {
    meeting_id: 'abc123def456'
  };

  const data = {
    query: `
      mutation($input: ConfirmUploadInput!) {
        confirmUpload(input: $input) {
          success
          meeting_id
          message
        }
      }
    `,
    variables: { input }
  };

  axios
    .post(url, data, { headers })
    .then(result => {
      console.log(result.data);
    })
    .catch(e => {
      console.log(JSON.stringify(e));
    });
  ```

  ```python python theme={null}
  import requests

  url = 'https://api.fireflies.ai/graphql'

  headers = {
      'Content-Type': 'application/json',
      'Authorization': 'Bearer your_api_key'
  }

  input_data = {
      "meeting_id": "abc123def456"
  }

  data = {
      'query': '''
          mutation($input: ConfirmUploadInput!) {
              confirmUpload(input: $input) {
                  success
                  meeting_id
                  message
              }
          }
      ''',
      'variables': {'input': input_data}
  }

  response = requests.post(url, headers=headers, json=data)

  if response.status_code == 200:
      print(response.json())
  else:
      print(response.text)
  ```
</RequestExample>

<ResponseExample>
  ```json Response theme={null}
  {
    "data": {
      "confirmUpload": {
        "success": true,
        "meeting_id": "abc123def456",
        "message": "Audio upload confirmed. Transcription has been queued."
      }
    }
  }
  ```
</ResponseExample>

## Complete Upload Flow Example

Here's a complete example showing the entire upload flow:

```javascript theme={null}
const axios = require('axios');
const fs = require('fs');

const API_URL = 'https://api.fireflies.ai/graphql';
const API_KEY = 'your_api_key';

async function uploadAudioFile(filePath, title) {
  const fileBuffer = fs.readFileSync(filePath);
  const fileSize = fileBuffer.length;
  
  // Step 1: Get the signed upload URL
  const createUrlResponse = await axios.post(API_URL, {
    query: `
      mutation($input: CreateUploadUrlInput!) {
        createUploadUrl(input: $input) {
          upload_url
          meeting_id
          expires_at
        }
      }
    `,
    variables: {
      input: {
        content_type: 'audio/mpeg',
        file_size: fileSize,
        title: title
      }
    }
  }, {
    headers: {
      'Content-Type': 'application/json',
      'Authorization': `Bearer ${API_KEY}`
    }
  });
  
  const { upload_url, meeting_id } = createUrlResponse.data.data.createUploadUrl;
  console.log('Got upload URL for meeting:', meeting_id);
  
  // Step 2: Upload the file to the signed URL
  await axios.put(upload_url, fileBuffer, {
    headers: {
      'Content-Type': 'audio/mpeg'
    }
  });
  console.log('File uploaded successfully');
  
  // Step 3: Confirm the upload
  const confirmResponse = await axios.post(API_URL, {
    query: `
      mutation($input: ConfirmUploadInput!) {
        confirmUpload(input: $input) {
          success
          meeting_id
          message
        }
      }
    `,
    variables: {
      input: {
        meeting_id: meeting_id
      }
    }
  }, {
    headers: {
      'Content-Type': 'application/json',
      'Authorization': `Bearer ${API_KEY}`
    }
  });
  
  console.log('Upload confirmed:', confirmResponse.data.data.confirmUpload);
  return meeting_id;
}

// Usage
uploadAudioFile('./meeting-recording.mp3', 'Team Standup')
  .then(meetingId => console.log('Transcription started for:', meetingId))
  .catch(err => console.error('Upload failed:', err));
```

## Error Codes

<Accordion title="object_not_found (UploadSession)">
  The upload session was not found or has expired. Upload sessions expire after 1 hour. You need to call `createUploadUrl` again to get a new upload URL.
</Accordion>

<Accordion title="object_not_found (Audio/Video)">
  The file was not found in storage. Make sure you have successfully uploaded the file to the signed URL before calling this mutation.
</Accordion>

## Important Notes

* Upload sessions expire after **1 hour**. If you don't confirm within this time, you'll need to start over with a new `createUploadUrl` call.
* Make sure the file upload to the signed URL completes successfully before calling `confirmUpload`.
* The `meeting_id` must match the one returned from `createUploadUrl`.
* Only the user who created the upload session can confirm it.

## Additional Resources

<CardGroup cols={2}>
  <Card title="Create Upload URL" icon="link" href="/graphql-api/mutation/create-upload-url">
    Generate a pre-signed URL for uploads
  </Card>

  <Card title="Webhooks" icon="link" href="/graphql-api/webhooks">
    Receive notifications when transcription completes
  </Card>

  <Card title="Transcript" icon="link" href="/graphql-api/query/transcript">
    Query the transcript after processing
  </Card>

  <Card title="Upload Audio (URL)" icon="link" href="/graphql-api/mutation/upload-audio">
    Alternative: Upload audio via public URL
  </Card>
</CardGroup>
