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

# Assets SDK quick start

> Install a StackShift SDK and upload files from Node/TypeScript, NestJS, Python, or Go.

<Tip>
  **Live.** This area is documented as current, user-reliable behavior.
</Tip>

## Goal

Upload a public asset and get a CDN URL with the official SDK.

## Prerequisites

* A StackShift API key
* An SDK installed in your backend app

## Workflow

<Steps>
  <Step>
    Create a StackShift client with apiKey.
  </Step>

  <Step>
    Call the Assets upload method with a file, bucket, key, visibility, and metadata.
  </Step>

  <Step>
    Store the returned asset ID in your app if you need later replacement or deletion.
  </Step>

  <Step>
    Use asset.url for originals, assets.url for transforms, videoUrl helpers for playback outputs, and version helpers for pinned delivery.
  </Step>
</Steps>

## TypeScript

```ts theme={null}
import { StackShift } from '@stackshift-cloud/sdk'

const stackshift = new StackShift({
  apiKey: process.env.STACKSHIFT_API_KEY!,
})

const asset = await stackshift.assets.upload(file, {
  bucket: 'avatars',
  key: 'users/user_123.png',
  visibility: 'public',
  metadata: { userId: 'user_123' },
})

console.log(asset.url)
```

## NestJS

Wrap the SDK in a service and accept files through NestJS Multer interceptors. For larger browser uploads, create signed upload URLs instead of buffering through the NestJS process.

```ts theme={null}
import { Injectable } from '@nestjs/common'
import { StackShift } from '@stackshift-cloud/sdk'

@Injectable()
export class AssetsService {
  private readonly stackshift = new StackShift({
    apiKey: process.env.STACKSHIFT_API_KEY!,
  })

  upload(file: Express.Multer.File) {
    return this.stackshift.assets.upload(
      new Blob([file.buffer], { type: file.mimetype }),
      {
        bucket: 'uploads',
        key: file.originalname,
        visibility: 'private',
        metadata: { originalName: file.originalname },
      },
    )
  }
}
```

```ts theme={null}
import { Controller, Post, UploadedFile, UseInterceptors } from '@nestjs/common'
import { FileInterceptor } from '@nestjs/platform-express'
import { AssetsService } from './assets.service'

@Controller('assets')
export class AssetsController {
  constructor(private readonly assets: AssetsService) {}

  @Post('upload')
  @UseInterceptors(FileInterceptor('file'))
  upload(@UploadedFile() file: Express.Multer.File) {
    return this.assets.upload(file)
  }
}
```

## React, Next.js, and TanStack Start

Browser apps should never receive the StackShift API key. Create a signed upload URL on a server route, then upload the browser File directly to StackShift Assets.

```ts Server route theme={null}
import { StackShift } from '@stackshift-cloud/sdk'

const stackshift = new StackShift({
  apiKey: process.env.STACKSHIFT_API_KEY!,
})

export async function createAvatarUpload() {
  return stackshift.assets.signedUploadUrl({
    bucket: 'avatars',
    key: `users/${crypto.randomUUID()}.png`,
    visibility: 'public',
    expiresIn: '10m',
    maxBytes: 5_000_000,
  })
}
```

```tsx Browser client theme={null}
async function uploadAvatar(file: File) {
  const upload = await fetch('/api/assets/avatar-upload', {
    method: 'POST',
  }).then((response) => response.json())

  await fetch(upload.url, {
    method: upload.method,
    body: file,
    headers: { 'Content-Type': file.type },
  })
}
```

## Python

```python theme={null}
from stackshift import StackShift

stackshift = StackShift(api_key="sk_live_...")

asset = stackshift.assets.upload(
    "avatar.png",
    bucket="avatars",
    key="users/user_123.png",
    visibility="public",
    metadata={"user_id": "user_123"},
)

print(asset["url"])
```

## Go

```go theme={null}
import (
    "context"
    "log"
    "os"

    stackshift "github.com/stackshiftCloud/assets-go"
)

client, err := stackshift.New(stackshift.Options{
    APIKey: os.Getenv("STACKSHIFT_API_KEY"),
})

file, _ := os.Open("avatar.png")
defer file.Close()

asset, err := client.Assets.Upload(ctx, stackshift.AssetUpload{
    File: file,
    FileName: "avatar.png",
    Bucket: "avatars",
    Key: "users/user_123.png",
    Visibility: "public",
})

log.Println(asset.URL)
```

## Expected result

<Check>
  Your app uploads a file to StackShift Assets and receives provider-neutral asset metadata.
</Check>

## Related guides

<CardGroup cols={2}>
  <Card title="StackShift Assets overview" href="/assets/overview">
    StackShift Assets is now a live media platform: storage, CDN delivery, image optimization, upload sessions, DAM, video, scanning, governance, AI metadata, and version history.
  </Card>

  <Card title="Direct browser uploads" href="/assets/direct-browser-uploads">
    Create a short-lived signed upload URL on your server, then PUT the file directly from the browser.
  </Card>

  <Card title="Image optimization" href="/assets/image-optimization">
    Use named presets and signed dynamic transforms for strict, cached, responsive image delivery.
  </Card>

  <Card title="AI DAM and versioning" href="/assets/ai-dam-and-versioning">
    Use OpenAI-backed asset intelligence, moderation, transcripts, smart crops, background removal, collections, saved searches, and branching versions.
  </Card>
</CardGroup>
