---
title: Quickstart
path: getting-started/quickstart
status: published
---

Upload your first file in five minutes. Assumes you have a ScaiDrive instance (managed or self-hosted) and a ScaiKey account on that instance.

## 1. Get an access token

ScaiDrive delegates authentication to ScaiKey. Log into the ScaiDrive web client and pull the token from the browser:

```javascript
// in your browser devtools console, while logged into the web client:
copy(localStorage.getItem("scaidrive.access_token"));
```

For server-to-server integrations, ask a tenant admin to issue a long-lived API token from ScaiKey's admin UI (**Applications → ScaiDrive → Service Tokens**). See [Authentication](/docs/scaidrive/getting-started/authentication) for the full OAuth flow.

Export it:

```bash
export SCAIDRIVE_TOKEN="eyJhbGc..."
export SCAIDRIVE_URL="https://scaidrive.scailabs.ai"
```

## 2. List your shares

```bash
curl -H "Authorization: Bearer $SCAIDRIVE_TOKEN" \
     $SCAIDRIVE_URL/api/v1/users/me/shares
```

```python
import httpx, os

resp = httpx.get(
    f"{os.environ['SCAIDRIVE_URL']}/api/v1/users/me/shares",
    headers={"Authorization": f"Bearer {os.environ['SCAIDRIVE_TOKEN']}"},
)
data = resp.json()
for share in data["shares"]:
    print(share["id"], share["name"], share["role"])
```

```typescript
const resp = await fetch(
  `${process.env.SCAIDRIVE_URL}/api/v1/users/me/shares`,
  { headers: { Authorization: `Bearer ${process.env.SCAIDRIVE_TOKEN}` } },
);
const data = await resp.json();
for (const s of data.shares) console.log(s.id, s.name, s.role);
```

The response looks like:

```json
{
  "shares": [
    {
      "id": "shr_01J3KXQ0N",
      "name": "Engineering",
      "type": "central",
      "role": "contributor",
      "owner_id": "grp_01J3KXQ0A",
      "quota_bytes": 107374182400,
      "used_bytes": 42301234567
    }
  ],
  "total": 1
}
```

Pick a `share_id` with `role` of `contributor`, `admin`, or `owner` — you need write access to upload.

## 3. Upload a file

Files upload as multipart form data. The `share_id` field is required; `folder_id` puts it in a subfolder instead of the share root.

```bash
curl -X POST $SCAIDRIVE_URL/api/v1/files \
  -H "Authorization: Bearer $SCAIDRIVE_TOKEN" \
  -F "share_id=shr_01J3KXQ0N" \
  -F "file=@./hello.txt"
```

```python
import httpx, os

with open("hello.txt", "rb") as f:
    resp = httpx.post(
        f"{os.environ['SCAIDRIVE_URL']}/api/v1/files",
        headers={"Authorization": f"Bearer {os.environ['SCAIDRIVE_TOKEN']}"},
        data={"share_id": "shr_01J3KXQ0N"},
        files={"file": ("hello.txt", f, "text/plain")},
    )
    resp.raise_for_status()
    print(resp.json())
```

```typescript
import { readFileSync } from "node:fs";

const form = new FormData();
form.append("share_id", "shr_01J3KXQ0N");
form.append(
  "file",
  new Blob([readFileSync("hello.txt")], { type: "text/plain" }),
  "hello.txt",
);

const resp = await fetch(`${process.env.SCAIDRIVE_URL}/api/v1/files`, {
  method: "POST",
  headers: { Authorization: `Bearer ${process.env.SCAIDRIVE_TOKEN}` },
  body: form,
});
console.log(await resp.json());
```

Response:

```json
{
  "id": "fil_01J3KXQ0Z",
  "name": "hello.txt",
  "size": 13,
  "version_id": "ver_01J3KXQ0Z",
  "checksum_sha256": "f7ff9e8b..."
}
```

(The upload endpoint returns the slim `FileUploadResponse` — `id`, `name`, `size`, `version_id`, `checksum_sha256`. Call `GET /api/v1/files/{id}` to get the full file metadata if you need `mime_type`, `created_at`, etc.)

## 4. Download the file back

```bash
curl -H "Authorization: Bearer $SCAIDRIVE_TOKEN" \
     -o hello-downloaded.txt \
     $SCAIDRIVE_URL/api/v1/files/fil_01J3KXQ0Z/content
```

```python
import httpx, os

resp = httpx.get(
    f"{os.environ['SCAIDRIVE_URL']}/api/v1/files/fil_01J3KXQ0Z/content",
    headers={"Authorization": f"Bearer {os.environ['SCAIDRIVE_TOKEN']}"},
)
with open("hello-downloaded.txt", "wb") as out:
    out.write(resp.content)
```

```typescript
const resp = await fetch(
  `${process.env.SCAIDRIVE_URL}/api/v1/files/fil_01J3KXQ0Z/content`,
  { headers: { Authorization: `Bearer ${process.env.SCAIDRIVE_TOKEN}` } },
);
const buffer = Buffer.from(await resp.arrayBuffer());
await import("node:fs").then((fs) =>
  fs.writeFileSync("hello-downloaded.txt", buffer),
);
```

That's it. You just uploaded and downloaded a file through the ScaiDrive API.

## 5. Create a public link

Share that file with someone who doesn't have a ScaiDrive account:

```bash
curl -X POST $SCAIDRIVE_URL/api/v1/external/links \
  -H "Authorization: Bearer $SCAIDRIVE_TOKEN" \
  -H "Content-Type: application/json" \
  -d '{
    "resource_type": "file",
    "resource_id": "fil_01J3KXQ0Z",
    "share_id": "shr_01J3KXQ0N",
    "link_type": "DOWNLOAD",
    "expires_in_days": 7,
    "password": "hunter2"
  }'
```

The response contains `url` — a shareable URL with an opaque token. Anyone with the URL and password can download for the next 7 days. See [External Links](/docs/scaidrive/api-guides/external-links) for IP allow-lists, upload drop-zones, and access notifications.

## What's next

- [Authentication](/docs/scaidrive/getting-started/authentication) — the full OAuth flow, token lifetimes, and scopes.
- [Your First Integration](/docs/scaidrive/getting-started/your-first-integration) — complete walk-through with error handling and retries.
- [Files](/docs/scaidrive/api-guides/files) — the full file API, including versioning, copy, and move.