Guide — Upload from Next.js
The APULODI SDK is server-side software. In Next.js the natural home is a route handler (App Router) — the SDK, the API key and the file bytes never touch the browser.
1. Set the environment variable
env
APULODI_API_KEY=apk_test_your_key_here
2. Upload route handler
app/api/uploads/route.ts:
ts
import { NextRequest, NextResponse } from "next/server";
import { Apulodi } from "@apulodi/sdk";
const apulodi = new Apulodi({
apiKey: process.env.APULODI_API_KEY!,
});
export async function POST(request: NextRequest) {
const form = await request.formData();
const file = form.get("file");
if (!(file instanceof File)) {
return NextResponse.json({ error: "missing_file" }, { status: 400 });
}
const result = await apulodi.files.upload({
file, // Blob/File — bytes go directly to storage
fileName: file.name,
contentType: file.type || "application/octet-stream",
path: "uploads",
});
return NextResponse.json({ id: result.id, filename: result.filename });
}
Why this is safe
The SDK runs inside the route handler on the server. Your APULODI_API_KEY
is never serialized into client JavaScript, and file bytes go straight from
the handler to storage via the presigned URL.
3. Browser form
html
<form id="upload">
<input type="file" name="file" />
<button type="submit">Upload</button>
</form>
<script>
document.getElementById("upload").addEventListener("submit", async (event) => {
event.preventDefault();
const form = new FormData(event.currentTarget);
await fetch("/api/uploads", { method: "POST", body: form });
});
</script>
4. Serve a download URL
app/api/files/[id]/download/route.ts:
ts
import { NextRequest, NextResponse } from "next/server";
import { Apulodi } from "@apulodi/sdk";
const apulodi = new Apulodi({ apiKey: process.env.APULODI_API_KEY! });
export async function GET(
_request: NextRequest,
{ params }: { params: Promise<{ id: string }> },
) {
const { id } = await params;
const { url, expiresAt } = await apulodi.files.downloadUrl(id, {
expiresInSeconds: 300,
});
return NextResponse.json({ url, expiresAt });
}
Your frontend can then fetch() that presigned URL (or point an <img> /
<a> at it) to stream the file directly from storage.
What to avoid
- ❌
import { Apulodi } from "@apulodi/sdk"inside Client Components. - ❌ Putting the API key in
NEXT_PUBLIC_*variables. - ❌ Using the SDK directly in the browser (it would need your key).
Next: Guide — Handling large files.