# Быстрый старт

Источник: https://dev.smartpdf.ru/docs/quickstart

## 1. Получите ключ

Зарегистрируйтесь на [smartpdf.ru](https://smartpdf.ru/register?from=dev) и подтвердите почту — на баланс API придёт 300 ₽, этого хватит примерно на 240 запросов. В личном кабинете, в разделе [«API и MCP»](https://smartpdf.ru/dashboard/api-keys), создайте ключ: он показывается один раз.

```bash
export SMARTPDF_API_KEY=sk_live_…
```

## 2. Выполните полный цикл

Пример сжимает `document.pdf` и сохраняет результат рядом — `document_smartpdf.pdf`. Код на всех языках проверен запуском против API.

### cURL

```bash
#!/usr/bin/env bash
# SmartPDF API — Сжать PDF: загрузка → операция → ожидание → скачивание.
# Нужны curl и jq.
# Ключ — в личном кабинете: https://smartpdf.ru/dashboard/api-keys
set -euo pipefail
API="https://api.smartpdf.ru/v1"
AUTH="X-API-Key: $SMARTPDF_API_KEY"

# 1. Загрузить файл
FILE_ID=$(curl -sS --fail-with-body -H "$AUTH" -F "file=@document.pdf" "$API/upload" | jq -r .file_id)

# 2. Запустить операцию
BODY=$(jq -n --arg file_id "$FILE_ID" '{file_id: $file_id, level: "medium"}')
TASK_ID=$(curl -sS --fail-with-body -H "$AUTH" -H "Content-Type: application/json" \
  -d "$BODY" "$API/pdf/compress" | jq -r .task_id)

# 3. Дождаться результата
while :; do
  TASK=$(curl -sS --fail-with-body -H "$AUTH" "$API/tasks/$TASK_ID")
  STATUS=$(echo "$TASK" | jq -r .status)
  [ "$STATUS" = done ] && break
  [ "$STATUS" = failed ] && { echo "Ошибка обработки: $(echo "$TASK" | jq -r .error)" >&2; exit 1; }
  sleep 2
done

# 4. Скачать результат
RESULT=$(curl -sS --fail-with-body -H "$AUTH" "$API/tasks/$TASK_ID/download")
curl -sS --fail-with-body -o "$(echo "$RESULT" | jq -r .filename)" "$(echo "$RESULT" | jq -r .download_url)"
echo "Готово: $(echo "$RESULT" | jq -r .filename)"
```

### Python

```python
# SmartPDF API — Сжать PDF: загрузка → операция → ожидание → скачивание.
# pip install requests
# Ключ — в личном кабинете: https://smartpdf.ru/dashboard/api-keys
import os
import time

import requests

API = "https://api.smartpdf.ru/v1"
HEADERS = {"X-API-Key": os.environ["SMARTPDF_API_KEY"]}


def call(method, path, **kwargs):
    response = requests.request(method, API + path, headers=HEADERS, timeout=60, **kwargs)
    if not response.ok:
        raise RuntimeError(f"{response.status_code}: {response.text}")
    return response.json()


# 1. Загрузить файл
with open("document.pdf", "rb") as f:
    file_id = call("POST", "/upload", files={"file": f})["file_id"]

# 2. Запустить операцию
task_id = call("POST", "/pdf/compress", json={"file_id": file_id, "level": "medium"})["task_id"]

# 3. Дождаться результата
while True:
    task = call("GET", f"/tasks/{task_id}")
    if task["status"] == "done":
        break
    if task["status"] == "failed":
        raise RuntimeError(task["error"] or "Ошибка обработки")
    time.sleep(2)

# 4. Скачать результат
result = call("GET", f"/tasks/{task_id}/download")
with open(result["filename"], "wb") as out:
    out.write(requests.get(result["download_url"], timeout=300).content)
print("Готово:", result["filename"])
```

### Node.js

```javascript
// SmartPDF API — Сжать PDF: загрузка → операция → ожидание → скачивание.
// Node.js 18+, без зависимостей; сохраните как quickstart.mjs.
// Ключ — в личном кабинете: https://smartpdf.ru/dashboard/api-keys
import { readFile, writeFile } from "node:fs/promises";

const API = "https://api.smartpdf.ru/v1";
const KEY = process.env.SMARTPDF_API_KEY;

async function call(path, { method = "GET", body, json } = {}) {
  const headers = { "X-API-Key": KEY };
  if (json) headers["Content-Type"] = "application/json";
  const res = await fetch(API + path, { method, headers, body: json ? JSON.stringify(json) : body });
  if (!res.ok) throw new Error(res.status + ": " + (await res.text()));
  return res.json();
}

async function upload(name) {
  const form = new FormData();
  form.append("file", new Blob([await readFile(name)]), name);
  return (await call("/upload", { method: "POST", body: form })).file_id;
}

// 1. Загрузить файл
const fileId = await upload("document.pdf");

// 2. Запустить операцию
const { task_id } = await call("/pdf/compress", { method: "POST", json: { file_id: fileId, level: "medium" } });

// 3. Дождаться результата
let task;
do {
  await new Promise((resolve) => setTimeout(resolve, 2000));
  task = await call("/tasks/" + task_id);
} while (task.status === "pending" || task.status === "processing");
if (task.status !== "done") throw new Error(task.error ?? "Ошибка обработки");

// 4. Скачать результат
const { download_url, filename } = await call("/tasks/" + task_id + "/download");
const file = await fetch(download_url);
await writeFile(filename, Buffer.from(await file.arrayBuffer()));
console.log("Готово:", filename);
```

### PHP

```php
<?php
// SmartPDF API — Сжать PDF: загрузка → операция → ожидание → скачивание.
// PHP 8 с расширением curl.
// Ключ — в личном кабинете: https://smartpdf.ru/dashboard/api-keys
const API = 'https://api.smartpdf.ru/v1';

function call(string $method, string $path, ?array $json = null, ?CURLFile $file = null): array
{
    $ch = curl_init(API . $path);
    $headers = ['X-API-Key: ' . getenv('SMARTPDF_API_KEY')];
    if ($json !== null) {
        $headers[] = 'Content-Type: application/json';
        curl_setopt($ch, CURLOPT_POSTFIELDS, json_encode($json, JSON_UNESCAPED_UNICODE));
    } elseif ($file !== null) {
        curl_setopt($ch, CURLOPT_POSTFIELDS, ['file' => $file]);
    }
    curl_setopt_array($ch, [
        CURLOPT_CUSTOMREQUEST => $method,
        CURLOPT_HTTPHEADER => $headers,
        CURLOPT_RETURNTRANSFER => true,
    ]);
    $body = curl_exec($ch);
    $status = curl_getinfo($ch, CURLINFO_RESPONSE_CODE);
    curl_close($ch);
    if ($body === false || $status >= 400) {
        throw new RuntimeException("$status: $body");
    }
    return json_decode($body, true);
}

// 1. Загрузить файл
$fileId = call('POST', '/upload', file: new CURLFile('document.pdf'))['file_id'];

// 2. Запустить операцию
$taskId = call('POST', '/pdf/compress', ['file_id' => $fileId, 'level' => 'medium'])['task_id'];

// 3. Дождаться результата
do {
    sleep(2);
    $task = call('GET', "/tasks/$taskId");
} while (in_array($task['status'], ['pending', 'processing'], true));
if ($task['status'] !== 'done') {
    throw new RuntimeException($task['error'] ?? 'Ошибка обработки');
}

// 4. Скачать результат
$result = call('GET', "/tasks/$taskId/download");
file_put_contents($result['filename'], file_get_contents($result['download_url']));
echo 'Готово: ' . $result['filename'] . PHP_EOL;
```

### Go

```go
// SmartPDF API — Сжать PDF: загрузка → операция → ожидание → скачивание.
// Go 1.21+, только стандартная библиотека.
// Ключ — в личном кабинете: https://smartpdf.ru/dashboard/api-keys
package main

import (
	"bytes"
	"encoding/json"
	"fmt"
	"io"
	"mime/multipart"
	"net/http"
	"os"
	"path/filepath"
	"time"
)

const api = "https://api.smartpdf.ru/v1"

func call(method, path string, body io.Reader, contentType string, out any) {
	req, err := http.NewRequest(method, api+path, body)
	check(err)
	req.Header.Set("X-API-Key", os.Getenv("SMARTPDF_API_KEY"))
	if contentType != "" {
		req.Header.Set("Content-Type", contentType)
	}
	res, err := http.DefaultClient.Do(req)
	check(err)
	defer res.Body.Close()
	data, err := io.ReadAll(res.Body)
	check(err)
	if res.StatusCode >= 400 {
		panic(fmt.Sprintf("%d: %s", res.StatusCode, data))
	}
	check(json.Unmarshal(data, out))
}

func upload(name string) string {
	var buf bytes.Buffer
	form := multipart.NewWriter(&buf)
	part, err := form.CreateFormFile("file", filepath.Base(name))
	check(err)
	data, err := os.ReadFile(name)
	check(err)
	part.Write(data)
	form.Close()
	var file struct {
		FileID string `json:"file_id"`
	}
	call("POST", "/upload", &buf, form.FormDataContentType(), &file)
	return file.FileID
}

func check(err error) {
	if err != nil {
		panic(err)
	}
}

func main() {
	// 1. Загрузить файл
	fileID := upload("document.pdf")

	// 2. Запустить операцию
	payload, _ := json.Marshal(map[string]any{"file_id": fileID, "level": "medium"})
	var task struct {
		TaskID string `json:"task_id"`
	}
	call("POST", "/pdf/compress", bytes.NewReader(payload), "application/json", &task)

	// 3. Дождаться результата
	var status struct{ Status, Error string }
	for status.Status != "done" {
		time.Sleep(2 * time.Second)
		call("GET", "/tasks/"+task.TaskID, nil, "", &status)
		if status.Status == "failed" {
			panic("Ошибка обработки: " + status.Error)
		}
	}

	// 4. Скачать результат
	var result struct {
		DownloadURL string `json:"download_url"`
		Filename    string `json:"filename"`
	}
	call("GET", "/tasks/"+task.TaskID+"/download", nil, "", &result)
	res, err := http.Get(result.DownloadURL)
	check(err)
	defer res.Body.Close()
	out, err := os.Create(result.Filename)
	check(err)
	defer out.Close()
	_, err = io.Copy(out, res.Body)
	check(err)
	fmt.Println("Готово:", result.Filename)
}
```

### Java

```java
// SmartPDF API — Сжать PDF: загрузка → операция → ожидание → скачивание.
// Java 17+ и Jackson (com.fasterxml.jackson.core:jackson-databind).
// Ключ — в личном кабинете: https://smartpdf.ru/dashboard/api-keys
import com.fasterxml.jackson.databind.JsonNode;
import com.fasterxml.jackson.databind.ObjectMapper;

import java.net.URI;
import java.net.http.HttpClient;
import java.net.http.HttpRequest;
import java.net.http.HttpResponse;
import java.nio.charset.StandardCharsets;
import java.nio.file.Files;
import java.nio.file.Path;
import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.UUID;

public class Quickstart {
    static final String API = "https://api.smartpdf.ru/v1";
    // HTTP/1.1: по http:// HttpClient иначе пытается перейти на HTTP/2 (h2c), что поддерживают не все серверы.
    static final HttpClient HTTP = HttpClient.newBuilder().version(HttpClient.Version.HTTP_1_1).build();
    static final ObjectMapper JSON = new ObjectMapper();

    static JsonNode call(HttpRequest.Builder request) throws Exception {
        HttpResponse<String> response = HTTP.send(
                request.header("X-API-Key", System.getenv("SMARTPDF_API_KEY")).build(),
                HttpResponse.BodyHandlers.ofString());
        if (response.statusCode() >= 400) {
            throw new RuntimeException(response.statusCode() + ": " + response.body());
        }
        return JSON.readTree(response.body());
    }

    static String upload(String name) throws Exception {
        String boundary = UUID.randomUUID().toString();
        byte[] head = ("--" + boundary + "\r\nContent-Disposition: form-data; name=\"file\"; filename=\""
                + Path.of(name).getFileName() + "\"\r\nContent-Type: application/octet-stream\r\n\r\n")
                .getBytes(StandardCharsets.UTF_8);
        byte[] tail = ("\r\n--" + boundary + "--\r\n").getBytes(StandardCharsets.UTF_8);
        return call(HttpRequest.newBuilder(URI.create(API + "/upload"))
                .header("Content-Type", "multipart/form-data; boundary=" + boundary)
                .POST(HttpRequest.BodyPublishers.ofByteArrays(
                        List.of(head, Files.readAllBytes(Path.of(name)), tail))))
                .get("file_id").asText();
    }

    public static void main(String[] args) throws Exception {
        // 1. Загрузить файл
        String fileId = upload("document.pdf");

        // 2. Запустить операцию
        String body = JSON.writeValueAsString(Map.of("file_id", fileId, "level", "medium"));
        String taskId = call(HttpRequest.newBuilder(URI.create(API + "/pdf/compress"))
                .header("Content-Type", "application/json")
                .POST(HttpRequest.BodyPublishers.ofString(body)))
                .get("task_id").asText();

        // 3. Дождаться результата
        JsonNode task;
        do {
            Thread.sleep(2000);
            task = call(HttpRequest.newBuilder(URI.create(API + "/tasks/" + taskId)));
        } while (Set.of("pending", "processing").contains(task.get("status").asText()));
        if (!task.get("status").asText().equals("done")) {
            throw new RuntimeException("Ошибка обработки: " + task.get("error").asText());
        }

        // 4. Скачать результат
        JsonNode result = call(HttpRequest.newBuilder(URI.create(API + "/tasks/" + taskId + "/download")));
        HTTP.send(HttpRequest.newBuilder(URI.create(result.get("download_url").asText())).build(),
                HttpResponse.BodyHandlers.ofFile(Path.of(result.get("filename").asText())));
        System.out.println("Готово: " + result.get("filename").asText());
    }
}
```

### C#

```csharp
// SmartPDF API — Сжать PDF: загрузка → операция → ожидание → скачивание.
// .NET 8: dotnet new console, замените Program.cs.
// Ключ — в личном кабинете: https://smartpdf.ru/dashboard/api-keys
using System.Net.Http.Json;
using System.Text.Json;

const string Api = "https://api.smartpdf.ru/v1";
using var http = new HttpClient { Timeout = TimeSpan.FromMinutes(5) };
http.DefaultRequestHeaders.Add("X-API-Key", Environment.GetEnvironmentVariable("SMARTPDF_API_KEY"));

async Task<JsonElement> Read(HttpResponseMessage response)
{
    var body = await response.Content.ReadAsStringAsync();
    if (!response.IsSuccessStatusCode) throw new Exception($"{(int)response.StatusCode}: {body}");
    return JsonDocument.Parse(body).RootElement;
}

async Task<string> Upload(string name)
{
    using var form = new MultipartFormDataContent();
    form.Add(new ByteArrayContent(await File.ReadAllBytesAsync(name)), "file", Path.GetFileName(name));
    return (await Read(await http.PostAsync($"{Api}/upload", form))).GetProperty("file_id").GetString()!;
}

// 1. Загрузить файл
var fileId = await Upload("document.pdf");

// 2. Запустить операцию
var task = await Read(await http.PostAsJsonAsync($"{Api}/pdf/compress", new { file_id = fileId, level = "medium" }));
var taskId = task.GetProperty("task_id").GetString();

// 3. Дождаться результата
JsonElement status;
do
{
    await Task.Delay(2000);
    status = await Read(await http.GetAsync($"{Api}/tasks/{taskId}"));
} while (status.GetProperty("status").GetString() is "pending" or "processing");
if (status.GetProperty("status").GetString() != "done")
    throw new Exception("Ошибка обработки: " + status.GetProperty("error"));

// 4. Скачать результат
var result = await Read(await http.GetAsync($"{Api}/tasks/{taskId}/download"));
var bytes = await http.GetByteArrayAsync(result.GetProperty("download_url").GetString());
await File.WriteAllBytesAsync(result.GetProperty("filename").GetString()!, bytes);
Console.WriteLine("Готово: " + result.GetProperty("filename").GetString());
```

## 3. Что дальше

- [Операции](https://dev.smartpdf.ru/docs/operations) — параметры каждой из 24 операций; шаг 2 меняется, остальное — как здесь.
- [Вебхуки](https://dev.smartpdf.ru/docs/webhooks) — уведомление о готовности вместо опроса статуса.
- [Ошибки](https://dev.smartpdf.ru/docs/errors) и [лимиты](https://dev.smartpdf.ru/docs/limits) — что проверять в продакшене.
- [MCP-сервер](https://dev.smartpdf.ru/docs/mcp) — те же операции для ИИ-агентов.
