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

# 360-Degree Video API

> Upload and process 360-degree vehicle videos for immersive inspections

## Overview

The 360-Degree Video API enables you to upload 360-degree videos of vehicles, automatically extract frames, and generate interactive 360-degree views for enhanced customer experiences. Perfect for showcasing vehicle exteriors, interiors, and detailed inspections.

## Key Features

<CardGroup cols={2}>
  <Card title="Video Upload" icon="upload">
    Upload 360-degree videos up to 100MB per file
  </Card>

  <Card title="Frame Extraction" icon="images">
    Automatic frame extraction at optimal intervals
  </Card>

  <Card title="Multiple Sides" icon="car-side">
    Support for OUTSIDE, INSIDE, and OPEN (trunk/hood) views
  </Card>

  <Card title="Cloud Storage" icon="cloud">
    Secure S3 storage with signed URL access
  </Card>
</CardGroup>

## Supported Video Formats

The API accepts the following video formats:

* **MP4** (.mp4) - Recommended
* **AVI** (.avi)
* **MOV** (.mov)
* **WMV** (.wmv)
* **FLV** (.flv)
* **WebM** (.webm)
* **MKV** (.mkv)
* **QuickTime** (.mov, .qt)

## Endpoints

### Upload 360 Video

<ParamField path="POST" type="endpoint">
  /360/upload
</ParamField>

Upload a 360-degree video file to S3 and trigger frame extraction.

**Content Type:** `multipart/form-data`

**Form Parameters:**

<ParamField body="video" type="file" required>
  Video file (max 100MB)
</ParamField>

<ParamField body="side" type="enum" required>
  Vehicle side: `OUTSIDE`, `INSIDE`, `OPEN`
</ParamField>

**Response:**

```json theme={null}
{
  "success": true,
  "message": "360 video uploaded successfully",
  "data": {
    "message": "Video uploaded and processing started",
    "jobId": "job_550e8400-e29b-41d4-a716",
    "video": {
      "key": "360/videos/job_550e8400/OUTSIDE/video.mp4",
      "url": "https://s3.amazonaws.com/bucket/360/videos/job_550e8400/OUTSIDE/video.mp4",
      "originalName": "exterior_360.mp4",
      "size": 45678901,
      "mimetype": "video/mp4",
      "jobId": "job_550e8400-e29b-41d4-a716"
    }
  }
}
```

**Response Fields:**

<ResponseField name="jobId" type="string">
  Unique job identifier for tracking processing status
</ResponseField>

<ResponseField name="key" type="string">
  S3 object key for the uploaded video
</ResponseField>

<ResponseField name="url" type="string">
  Public URL of the uploaded video
</ResponseField>

<ResponseField name="originalName" type="string">
  Original filename
</ResponseField>

<ResponseField name="size" type="number">
  File size in bytes
</ResponseField>

<ResponseField name="mimetype" type="string">
  MIME type of the file
</ResponseField>

**Example Request:**

```bash theme={null}
curl -X POST "https://api.steerai.autos/v1/360/upload" \
  -H "Authorization: Bearer YOUR_API_KEY" \
  -F "video=@exterior_360.mp4" \
  -F "side=OUTSIDE"
```

***

### Get Processed Frames

<ParamField path="GET" type="endpoint">
  /360/frames
</ParamField>

Retrieve extracted frames from a processed 360 video with signed URLs.

**Query Parameters:**

<ParamField query="jobId" type="string" required>
  Job ID from video upload
</ParamField>

<ParamField query="side" type="enum" required>
  Vehicle side: `OUTSIDE`, `INSIDE`, `OPEN`
</ParamField>

**Response:**

```json theme={null}
{
  "success": true,
  "message": "Frames retrieved successfully",
  "data": {
    "message": "360 frames found",
    "jobId": "job_550e8400-e29b-41d4-a716",
    "side": "OUTSIDE",
    "frames": [
      "https://s3.amazonaws.com/bucket/360/frames/job_550e8400/OUTSIDE/frame_001.jpg?X-Amz-Signature=...",
      "https://s3.amazonaws.com/bucket/360/frames/job_550e8400/OUTSIDE/frame_002.jpg?X-Amz-Signature=...",
      "https://s3.amazonaws.com/bucket/360/frames/job_550e8400/OUTSIDE/frame_003.jpg?X-Amz-Signature=..."
    ],
    "frameCount": 72
  }
}
```

**Response Fields:**

<ResponseField name="frames" type="array">
  Array of signed URLs for frame images (valid for 1 hour)
</ResponseField>

<ResponseField name="frameCount" type="number">
  Total number of extracted frames
</ResponseField>

<Info>
  Frame URLs are signed and expire after 1 hour. Generate new URLs by calling this endpoint again.
</Info>

***

### Get Mask Frames

<ParamField path="GET" type="endpoint">
  /360/mask-frames
</ParamField>

Retrieve processed mask frames (used for AI detection overlays) with signed URLs.

**Query Parameters:**

<ParamField query="carId" type="string" required>
  Vehicle UUID
</ParamField>

<ParamField query="side" type="enum" required>
  Vehicle side: `OUTSIDE`, `INSIDE`, `OPEN`
</ParamField>

**Response:**

```json theme={null}
{
  "success": true,
  "message": "Mask frames retrieved successfully",
  "data": {
    "message": "360 mask frames found",
    "carId": "car_550e8400-e29b-41d4-a716",
    "side": "OUTSIDE",
    "frames": [
      "https://s3.amazonaws.com/bucket/360/masks/car_550e8400/OUTSIDE/mask_001.png?X-Amz-Signature=...",
      "https://s3.amazonaws.com/bucket/360/masks/car_550e8400/OUTSIDE/mask_002.png?X-Amz-Signature=..."
    ],
    "frameCount": 72
  }
}
```

<Info>
  Mask frames show AI-detected damage areas overlaid on the vehicle images.
</Info>

***

### Cleanup 360 Data

<ParamField path="POST" type="endpoint">
  /360/cleanup
</ParamField>

Delete 360 video data and frames for a specific vehicle and side. Used to manage storage and remove outdated content.

**Request Body:**

```json theme={null}
{
  "carId": "car_550e8400-e29b-41d4-a716",
  "side": "OUTSIDE",
  "removeProcessed": true
}
```

<ParamField body="carId" type="string" required>
  Vehicle UUID
</ParamField>

<ParamField body="side" type="enum" required>
  Vehicle side: `OUTSIDE`, `INSIDE`, `OPEN`
</ParamField>

<ParamField body="removeProcessed" type="boolean">
  Also remove processed frames (default: true)
</ParamField>

**Response:**

```json theme={null}
{
  "success": true,
  "message": "360 data cleaned up successfully",
  "data": {
    "filesDeleted": 73,
    "rawVideoDeleted": true,
    "framesDeleted": true,
    "masksDeleted": true
  }
}
```

<Warning>
  This operation permanently deletes video and frame data. This action cannot be undone.
</Warning>

***

## 360 Video Workflow

```mermaid theme={null}
graph TD
    A[Record 360 Video] --> B[Upload Video]
    B --> C[Video Stored in S3]
    C --> D[Processing Job Created]
    D --> E[Frame Extraction]
    E --> F[Store Frames in S3]
    F --> G[AI Damage Detection]
    G --> H[Generate Mask Frames]
    H --> I[Frames Ready]
    I --> J[Display 360 Viewer]
    J --> K{Need to Update?}
    K -->|Yes| L[Cleanup Old Data]
    L --> A
    K -->|No| M[Keep Displaying]

    style B fill:#282F75
    style I fill:#4360B1
    style J fill:#28a745
```

## Vehicle Sides Explained

### OUTSIDE

Complete exterior 360-degree view showing:

* All four sides of the vehicle
* Wheels and tires
* Exterior condition
* Paint quality
* Body damage or dents

**Best Practice:** Walk around the vehicle in a complete circle, keeping the phone/camera at consistent height.

### INSIDE

Complete interior 360-degree view showing:

* Dashboard and controls
* Front and rear seats
* Center console
* Interior condition
* All cabin features

**Best Practice:** Record from the driver's seat, then passenger side for full coverage.

### OPEN

Open compartments and storage:

* Trunk/boot space
* Engine bay
* Under hood inspection
* Storage compartments

**Best Practice:** Position camera to show full depth and all visible components.

## File Size Considerations

| Quality       | Resolution | Duration | Approx. Size | Recommended     |
| ------------- | ---------- | -------- | ------------ | --------------- |
| **Standard**  | 1080p      | 30-60s   | 20-40 MB     | ✅ Yes           |
| **High**      | 2K         | 30-60s   | 40-70 MB     | ✅ Yes           |
| **Ultra**     | 4K         | 30-60s   | 70-100 MB    | ⚠️ Max limit    |
| **Too Large** | 4K+        | 60s+     | 100+ MB      | ❌ Exceeds limit |

<Warning>
  Files larger than 100MB will be rejected. Compress videos if necessary while maintaining quality.
</Warning>

## Frame Extraction Details

### Automatic Extraction

* **Frame Rate:** 5 frames per second (configurable)
* **Total Frames:** \~60-120 frames per video
* **Format:** JPEG images (optimized quality)
* **Resolution:** Maintains source resolution
* **Processing Time:** 1-3 minutes typical

### Frame Naming Convention

Frames are named sequentially:

```
frame_001.jpg
frame_002.jpg
frame_003.jpg
...
frame_072.jpg
```

## Use Cases

### Example 1: Complete Vehicle Upload

```bash theme={null}
# Upload exterior 360 video
curl -X POST "https://api.steerai.autos/v1/360/upload" \
  -H "Authorization: Bearer YOUR_API_KEY" \
  -F "video=@exterior_360.mp4" \
  -F "side=OUTSIDE"

# Upload interior 360 video
curl -X POST "https://api.steerai.autos/v1/360/upload" \
  -H "Authorization: Bearer YOUR_API_KEY" \
  -F "video=@interior_360.mp4" \
  -F "side=INSIDE"

# Upload trunk/engine 360 video
curl -X POST "https://api.steerai.autos/v1/360/upload" \
  -H "Authorization: Bearer YOUR_API_KEY" \
  -F "video=@open_360.mp4" \
  -F "side=OPEN"
```

### Example 2: Retrieve and Display Frames

```javascript theme={null}
// Fetch frames after processing
async function get360Frames(jobId, side) {
  const response = await fetch(
    `https://api.steerai.autos/v1/360/frames?jobId=${jobId}&side=${side}`,
    {
      headers: { 'Authorization': `Bearer ${API_KEY}` }
    }
  );

  const { data } = await response.json();
  return data.frames;
}

// Display in 360 viewer
async function display360View(jobId) {
  const frames = await get360Frames(jobId, 'OUTSIDE');

  // Initialize 360 viewer library
  const viewer = new Viewer360({
    container: '#viewer-container',
    frames: frames,
    autoRotate: true,
    rotationSpeed: 2
  });
}
```

### Example 3: Storage Management

```bash theme={null}
# Clean up old 360 data
curl -X POST "https://api.steerai.autos/v1/360/cleanup" \
  -H "Authorization: Bearer YOUR_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "carId": "car_550e8400-e29b-41d4-a716",
    "side": "OUTSIDE",
    "removeProcessed": true
  }'
```

## Error Codes

| Code                 | Status | Description                    |
| -------------------- | ------ | ------------------------------ |
| `FILE_TOO_LARGE`     | 413    | Video exceeds 100MB limit      |
| `INVALID_FILE_TYPE`  | 400    | Unsupported video format       |
| `MISSING_VIDEO_FILE` | 400    | No video file provided         |
| `INVALID_SIDE`       | 400    | Invalid vehicle side specified |
| `JOB_NOT_FOUND`      | 404    | Processing job ID not found    |
| `FRAMES_NOT_READY`   | 404    | Frames not yet processed       |
| `UPLOAD_FAILED`      | 500    | S3 upload error                |
| `PROCESSING_FAILED`  | 500    | Frame extraction failed        |

## Best Practices

<AccordionGroup>
  <Accordion title="Record in good lighting">
    Natural daylight or well-lit showroom provides best results. Avoid shadows and glare.
  </Accordion>

  <Accordion title="Maintain consistent speed">
    Walk at a steady pace around the vehicle. Too fast creates blurry frames.
  </Accordion>

  <Accordion title="Keep camera level">
    Maintain consistent height and angle for professional-looking results.
  </Accordion>

  <Accordion title="Clean the vehicle first">
    Remove dirt, debris, and clutter for the best presentation.
  </Accordion>

  <Accordion title="Check file size before upload">
    Compress large videos while maintaining quality to stay under 100MB limit.
  </Accordion>

  <Accordion title="Upload all three sides">
    Complete OUTSIDE, INSIDE, and OPEN views provide comprehensive coverage.
  </Accordion>

  <Accordion title="Regularly cleanup old data">
    Use the cleanup endpoint to manage storage costs and remove outdated videos.
  </Accordion>
</AccordionGroup>

## Integration with Vehicles API

The 360 Video API integrates seamlessly with the Vehicles API:

```javascript theme={null}
// Complete vehicle listing workflow
async function createVehicleWith360(vehicleData, videoFiles) {
  // Step 1: Create vehicle
  const vehicle = await createVehicle(vehicleData);

  // Step 2: Upload 360 videos
  const outsideJob = await upload360Video(videoFiles.outside, 'OUTSIDE');
  const insideJob = await upload360Video(videoFiles.inside, 'INSIDE');
  const openJob = await upload360Video(videoFiles.open, 'OPEN');

  // Step 3: Wait for processing
  await waitForProcessing([outsideJob.jobId, insideJob.jobId, openJob.jobId]);

  // Step 4: Get frames
  const outsideFrames = await get360Frames(outsideJob.jobId, 'OUTSIDE');
  const insideFrames = await get360Frames(insideJob.jobId, 'INSIDE');
  const openFrames = await get360Frames(openJob.jobId, 'OPEN');

  // Step 5: Update vehicle with frame URLs
  await updateVehicle(vehicle.id, {
    media360: {
      outside: outsideFrames,
      inside: insideFrames,
      open: openFrames
    }
  });

  return vehicle;
}
```

## Related Resources

<CardGroup cols={2}>
  <Card title="Vehicles API" icon="car" href="/api-reference/vehicles/overview">
    Manage vehicle inventory and listings
  </Card>

  <Card title="Visual Inspection API" icon="camera" href="/api-reference/inspection/visual-inspection">
    AI-powered damage detection
  </Card>

  <Card title="Media Best Practices" icon="images" href="/guides/media-best-practices">
    Guidelines for vehicle photography and video
  </Card>

  <Card title="Storage Management" icon="database" href="/guides/storage-management">
    Optimize media storage costs
  </Card>
</CardGroup>
