Set PDF permissions
The PDF permissions validator turns a user-supplied list of access flags into one predictable permission set.
Run — free
Runs in your browser. Free, unlimited — your data never leaves this page.
Provide a PDF reference and any combination of print, copy, edit, and annotate. The result uses lowercase canonical names, removes duplicates, and follows a stable order. If the list contains an unsupported name, the request fails clearly instead of passing an ambiguous policy to the next step in your document workflow. This keeps automated configurations consistent and reviewable.
Define the policy before changing the document
PDF security workflows often begin with a small configuration object long before an encryption library or document service touches the file. That configuration deserves the same validation as the document itself. A misspelled flag such as “printing” may otherwise be ignored, interpreted differently by separate libraries, or stored as if it were valid. This capability provides a narrow contract for that boundary. Send the PDF reference together with the permission names you intend to allow. The validator confirms that the PDF reference is present and that permissions is an array containing only print, copy, edit, and annotate. It then returns the accepted names in canonical order. It does not download, inspect, encrypt, or rewrite the PDF. Keeping validation separate makes the result useful as a safe input to a later protection step, a policy database, an approval screen, or an audit record. It also lets an application reject a bad selection immediately, before starting a slower or more expensive document operation.
How normalization produces a stable result
Permission lists frequently arrive from checkboxes, command-line arguments, imported settings, or several combined rules. Those sources can produce mixed capitalization, surrounding spaces, repeated values, and inconsistent ordering. The normalizer trims each string and converts it to lowercase before checking it against the supported vocabulary. Duplicate flags collapse into one entry because permissions represent a set rather than a sequence of commands. The output order is always print, copy, edit, then annotate, regardless of the order in which valid values were supplied. An empty array is valid and represents a policy that grants none of these four permissions. Any non-string value or unknown name makes the whole request fail with an invalid-input error; the tool never silently drops an unsupported flag. This all-or-nothing behavior is important for security-related settings because a partially accepted policy can misrepresent what the caller requested. The deterministic output is also straightforward to compare, cache, sign, review, and test across environments.
Use the normalized set in a complete PDF workflow
The returned array is a validated policy description, not a modified document. Pass it to the component that actually applies PDF encryption or owner-level restrictions, and consult that component’s documentation for the exact behavior of readers and operating systems. PDF permissions are generally advisory controls enforced by compliant software; they are not a substitute for access control, careful distribution, or encryption with an appropriate password. Separating policy validation from enforcement still has practical benefits. A web form can show a clean summary before submission, an API can store one consistent representation instead of many equivalent arrays, and a batch job can stop on the first unknown flag rather than producing files with uncertain settings. Because this capability uses no network service and does not decode the supplied PDF, it can run in the browser with the same deterministic result as the API. Browser use is free, while automated API requests use the published $0.002 base price. No document content is returned or retained by this validator.
What you can do with it
Validate a permissions form
Normalize checkbox values before sending a PDF protection request and show the user the exact accepted policy.
Standardize stored document policies
Remove duplicates and ordering differences before saving permission sets in a database or audit log.
Reject unsafe configuration mistakes
Fail a batch workflow when an integration sends an unknown permission name instead of silently ignoring it.
FAQ
Does this capability modify or encrypt the PDF?
No. It validates the PDF reference and permission names, then returns a normalized permission set. Apply that set with a separate PDF protection tool.
Which permission flags are supported?
The supported canonical names are print, copy, edit, and annotate.
What happens when a flag is unknown?
The request fails with an invalid-input error that identifies the unknown value and lists the allowed flags.
Are duplicate and uppercase values accepted?
Yes. Surrounding whitespace is removed, names are converted to lowercase, and duplicate permissions are collapsed.
Can I provide an empty permission list?
Yes. An empty array is normalized to an empty array and represents granting none of the four supported permissions.
How much does it cost?
It is free to run in the browser on this page. API automation costs $0.002 per request.
For developers — API access
Everything on this page is available programmatically. This section is for teams who want to wire it into their own systems; everyone else can just use the tool above.
API endpoint
Prefer to automate it? One authenticated POST creates the task; the result comes back by webhook or a signed link. The same capability also runs here on the web, by email and from Telegram — and soon from our app too.
Call it from your stack
curl -X POST https://api.kit.forhosting.com/pdf/permissions-set \
-H "Authorization: Bearer $KIT_KEY" \
-H "Content-Type: application/json" \
-d '{"pdf":"kit://upl_example_pdf","permissions":["print","copy"]}'const res = await fetch("https://api.kit.forhosting.com/pdf/permissions-set", {
method: "POST",
headers: {
"Authorization": `Bearer ${process.env.KIT_KEY}`,
"Content-Type": "application/json"
},
body: JSON.stringify({
"pdf": "kit://upl_example_pdf",
"permissions": [
"print",
"copy"
]
})
});
const { task_id } = await res.json();import os, requests
res = requests.post(
"https://api.kit.forhosting.com/pdf/permissions-set",
headers={"Authorization": f"Bearer {os.environ['KIT_KEY']}"},
json={
"pdf": "kit://upl_example_pdf",
"permissions": [
"print",
"copy"
]
},
)
task_id = res.json()["task_id"]<?php
$res = file_get_contents("https://api.kit.forhosting.com/pdf/permissions-set", false, stream_context_create([
"http" => [
"method" => "POST",
"header" => "Authorization: Bearer " . getenv("KIT_KEY") . "\r\nContent-Type: application/json",
"content" => '{"pdf":"kit://upl_example_pdf","permissions":["print","copy"]}',
],
]));
$task = json_decode($res, true);body := bytes.NewBufferString(`{"pdf":"kit://upl_example_pdf","permissions":["print","copy"]}`)
req, _ := http.NewRequest("POST", "https://api.kit.forhosting.com/pdf/permissions-set", body)
req.Header.Set("Authorization", "Bearer "+os.Getenv("KIT_KEY"))
req.Header.Set("Content-Type", "application/json")
res, _ := http.DefaultClient.Do(req)Example request
{
"pdf": "kit://upl_example_pdf",
"permissions": [
"print",
"copy"
]
}Example response
{
"task_id": "tsk_a1b2c3d4e5f6a1b2c3d4e5f6",
"type": "pdf.permissions_set",
"status": "queued",
"_links": {
"result": "/tasks/tsk_…/result"
}
}The API is asynchronous: the call returns a task_id immediately and the result arrives by webhook. Polling is capped at 1 req/s per task.
Pricing
Published price — no tokens, no invented credits. A failed task is never charged.
Limits
max_mb | 25 |
max_pages | 200 |
Errors
| HTTP | Code | Meaning |
|---|---|---|
401 | unauthorized | Missing or invalid API key. |
402 | insufficient_balance | Your balance doesn't cover the task price. |
404 | unknown_type | That task type doesn't exist. |
429 | rate_limited | Too many requests. Use the webhook instead of polling. |