Skip to content

Commit 57e2bbb

Browse files
committed
chore: update pre-signed URLs docs
1 parent caf32cc commit 57e2bbb

File tree

2 files changed

+101
-9
lines changed

2 files changed

+101
-9
lines changed

sources/platform/collaboration/general-resource-access.md

Lines changed: 101 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -125,25 +125,117 @@ await datasetClient.update({
125125

126126
Even when a resource is restricted, you might still want to share it with someone outside your team — for example, to send a PDF report to a client, or include a screenshot in an automated email or Slack message. In these cases, **storage resources** (like key-value stores, datasets, and request queues) support generating **pre-signed URLs**. These are secure, time-limited links that let others access individual files without needing an Apify account or authentication.
127127

128-
Pre-signed URLs:
128+
#### How pre-signed URLs work
129+
A pre-signed URL is a regular HTTPS link that includes a cryptographic signature verifying that access has been explicitly granted by someone with valid permissions.
130+
When the signed URL is used, Apify validates the signature and grants temporary access only to the file or record it refers to - no API token required.
129131

130-
- Work even when General resource access is restricted
131-
- Expire automatically after 14 days (by default)
132-
- Are scoped to a single resource (prevents access to other records)
133-
- Are ideal for sharing screenshots, reports, or any other one-off files
132+
**Key properties**:
133+
- **Works with restricted resources** – Even if “General resource access” is set to **Restricted**, the signed URL will work without asking for API token.
134+
**Time-limited (optional)** – Links can be either **temporary** (expiring after a specified duration) or **permanent**, depending on how they’re generated.
135+
**Lightweight** - Ideal for embedding in emails, webhooks, reports, or notifications where authentication isn’t possible.
136+
137+
#### What links can be pre-signed
138+
139+
Only selected **dataset** and **key-value store** endpoints support pre-signed URLs.
140+
This allows fine-grained control over what data can be shared without authentication.
141+
142+
| Resource | Link | Validity | Notes |
143+
|-----------|-----------------------|------|-------|
144+
| **Datasets** | Dataset items (`/v2/datasets/:datasetId/items`) | Temporary or Permanent | The link provides access to all dataset items. |
145+
| **Key-value stores** | List of keys (`/v2/key-value-stores/:storeId/keys`) | Temporary or Permanent | Returns the list of keys in a store. |
146+
| **Key-value stores** | Single record (`/v2/key-value-stores/:storeId/records/:recordKey`) | **Permanent only** | The public URL for a specific record is always permanent - it stays valid as long as the record exists. |
147+
148+
:::info Automatically generated signed URLs
149+
150+
When you retrieve dataset or key-value store details using:
151+
152+
- `GET https://api.apify.com/v2/datasets/:datasetId`
153+
- `GET https://api.apify.com/v2/key-value-stores/:storeId`
154+
155+
the API response includes automatically generated fields:
156+
157+
- `itemsPublicUrl` – a pre-signed URL providing access to dataset items
158+
- `keysPublicUrl` – a pre-signed URL providing access to key-value store keys
159+
160+
These automatically generated URLs are **valid for 14 days**.
161+
162+
The response also contains:
163+
- `consoleUrl` - provides a stable link to the resource's page in the Apify Console. Unlike a direct API link, Console link will prompt unauthenticated users to sign in, ensuring they have required permissions to view the resource.
164+
165+
:::
166+
167+
#### How to generate pre-signed URLs
168+
You can create pre-signed URLs either through the Apify Console or programmatically via the API or SDK.
169+
170+
**In console:**
134171

135172
To generate a pre-signed link, you can use the **Export** button in Console, or call the appropriate API client method.
136173

137-
![Generating shareable link for a restricted storage resource](./images/general-resouce-access/copy-shareable-link.png)
174+
**1. Using the Apify Console**
175+
176+
:::note
177+
178+
The link will include a signature **only if the general resource access is set to Restricted**. For unrestricted datasets, the link will work without a signature.
179+
180+
:::
181+
182+
- **Dataset items:**
183+
1. Click the **Export** button.
184+
2. In the modal that appears, click **Copy shareable link**.
138185

139-
:::info Console links for resources
186+
![Generating shareable link for a restricted storage resource](./images/general-resouce-access/copy-shareable-link.png)
140187

141-
Resource objects returned by the API and clients (like `apify-client-js`) include a `consoleUrl` property. This provides a stable link to the resource's page in the Apify Console. Unlike a direct API link, Console link will prompt unauthenticated users to sign in, ensuring they have required permissions to view the resource.
188+
- **Key-value store records:**
189+
1. Open a key-value store.
190+
2. Navigate to the record you want to share.
191+
3. In the **Actions** column, click the link icon to **copy signed link**.
142192

143-
This is ideal for use-cases like email notifications or other automated workflows.
193+
![Copy pre-signed URL for KV store record](./images/general-resouce-access/copy-record-url-kv-store.png)
194+
195+
**2. Using the Apify Client**
196+
197+
You can generate pre-signed URLs programmatically for datasets and key-value stores:
198+
199+
```js
200+
import { ApifyClient } from "apify-client";
201+
const client = new ApifyClient({ token: process.env.APIFY_TOKEN });
202+
203+
// Dataset items
204+
const dataset = client.dataset('my-dataset-id');
205+
206+
// Creates pre-signed URL for items (expires in 7 days)
207+
const itemsUrl = await dataset.createItemsPublicUrl({ expiresInSecs: 7 * 24 * 3600 });
208+
209+
// Creates permanent pre-signed URL for items
210+
const permanentItemsUrl = await dataset.createItemsPublicUrl();
211+
212+
// Key-value store
213+
const store = client.keyValueStore('my-store-id');
214+
215+
// Get permanent URL for a single record
216+
const recordUrl = store.getRecordPublicUrl('report.pdf');
217+
218+
// Create pre-signed URL for list of keys (expires in 1 day)
219+
const keysPublicUrl = await store.createKeysPublicUrl({ expiresInSecs: 24 * 3600 });
220+
221+
// Create permanent pre-signed URL for list of keys
222+
const permanentKeysPublicUrl = await store.createKeysPublicUrl();
223+
```
224+
225+
:::tip Permanent signed URL
226+
227+
If the `expiresInSecs` option is not specified, the generated link will be **permanent**.
144228

145229
:::
146230

231+
**3. Signing URLs manually (Advanced)**
232+
233+
If you need finer control - for example, generating links without using Apify client — you can sign URLs manually using our reference implementation.
234+
235+
👉 [See reference implementation in Apify clients](https://github.com/apify/apify-client-js/blob/5efd68a3bc78c0173a62775f79425fad78f0e6d1/src/resource_clients/dataset.ts#L179)
236+
237+
Manual signing uses standard **HMAC (SHA-256)** with `urlSigningSecretKey` of the resource and can be easily integrated.
238+
147239
### Sharing storages by name
148240

149241
A convenient feature of storages is that you can name them. If you choose to do so there is an extra access level setting that applies to storages only, which is **Anyone with name or ID can read**. In that case anyone that knows the storage name is able to read it via API or view it using the storages Console URL.
179 KB
Loading

0 commit comments

Comments
 (0)