Share Secrets
Generate secure one-time links for sensitive data transmission with automated content purging and access tracking.
Share Secrets API
The Share Secrets API provides a secure mechanism for transmitting sensitive information (such as passwords, private keys, or PII) without leaving a persistent digital footprint. Secrets are encrypted and associated with a unique, short-lived URL. To ensure maximum security, content is purged immediately after the first successful access, rendering the link permanently invalid.
Secret Management
Audit Secret Inventory
Retrieve a paginated directory of all active (unread) or recently expired share secret entries. This allows for administrative tracking of shared links and their current consumption status.
share_secrets:readPath, query, and header parameters
sizepageResponses
Secret directory successfully retrieved.
{
"entities": "ShareSecret",
"count": 5,
"per_page": 100,
"pages": {
"current": 1,
"max": 1
},
"elements": [
{
"id": "6739782b...",
"name": "Database Migration Credentials",
"url": "https://hub.donutwork.com/ss/b6a9532aa4a06...",
"readed": false
}
]
}Request examples
curl --request GET 'https://api.hub.donutwork.com/2026-02-01/share-secrets.json' \
--header 'Authorization: Bearer YOUR_API_KEY'const response = await fetch('https://api.hub.donutwork.com/2026-02-01/share-secrets.json', {
method: 'GET',
headers: {
Authorization: 'Bearer ' + process.env.DONUTWORK_API_KEY,
},
});
const requestId = response.headers.get('x-request-id');
if (!response.ok) {
const error = await response.text();
throw new Error(`${response.status} ${error} [${requestId}]`);
}
const contentType = response.headers.get('content-type') ?? '';
const data = response.status === 204 ? null
: contentType.includes('application/json') ? await response.json()
: await response.text();$request = curl_init('https://api.hub.donutwork.com/2026-02-01/share-secrets.json');
curl_setopt_array($request, [
CURLOPT_CUSTOMREQUEST => 'GET',
CURLOPT_RETURNTRANSFER => true,
CURLOPT_HTTPHEADER => [
'Authorization: Bearer ' . getenv('DONUTWORK_API_KEY'),
],
]);
$response = curl_exec($request);
if ($response === false) {
$error = curl_error($request);
curl_close($request);
throw new RuntimeException($error);
}
$status = curl_getinfo($request, CURLINFO_RESPONSE_CODE);
$contentType = (string) curl_getinfo($request, CURLINFO_CONTENT_TYPE);
curl_close($request);
if ($status >= 400) { throw new RuntimeException($response); }
$data = $status === 204 ? null
: (str_contains($contentType, 'application/json')
? json_decode($response, true, flags: JSON_THROW_ON_ERROR) : $response);Replace uppercase placeholders and sample values with your own data and company resource IDs. Keep the API key on a trusted server. Reuse an idempotency key only for the same logical request and payload.
Provision Secure Secret Link
Generate a new ephemeral secret link. The content provided is encrypted at rest and will be revealed only once. You can optionally trigger an automated email notification to the recipient.
Set requirePin to true to require a server-generated six-digit PIN before
the recipient can reveal the content. The PIN is returned as pin_code only
in the creation response; send it separately. Notification emails contain the
link and optional message, never the PIN. Without requirePin, PIN protection
defaults to false. Invalid recipient addresses or non-boolean requirePin
values return 422 before creating a secret. If email delivery fails after
creation, the response retains the link and reports sendTo.status: false;
do not repeat creation just to retry delivery.
share_secrets:writePath, query, and header parameters
No path, query, or additional header parameters.
Request Body
{
"shareSecret": {
"name": "Deployment API Token",
"content": "secret_value_redacted",
"requirePin": true,
"sendTo": {
"email": "engineer@partner-company.com",
"message": "The requested production API token is now available for one-time retrieval."
}
}
}shareSecret.nameRequiredshareSecret.contentRequiredshareSecret.requirePinshareSecret.sendTo.emailshareSecret.sendTo.messageResponses
Secret link successfully provisioned.
{
"id": "67397a4c...",
"name": "Deployment API Token",
"url": "https://hub.donutwork.com/ss/fb89f610...",
"readed": false,
"pin_required": true,
"pin_code": "123456",
"readerInfo": {
"ip": null,
"ua": null,
"isoDate": null,
"ts": null
},
"sendTo": {
"status": true,
"messageId": "msg_9921"
}
}Request examples
curl --request POST 'https://api.hub.donutwork.com/2026-02-01/share-secrets.json' \
--header 'Authorization: Bearer YOUR_API_KEY' \
--header 'Content-Type: application/json' \
--data '{
"shareSecret": {
"name": "Deployment API Token",
"content": "secret_value_redacted",
"requirePin": true,
"sendTo": {
"email": "engineer@partner-company.com",
"message": "The requested production API token is now available for one-time retrieval."
}
}
}'const response = await fetch('https://api.hub.donutwork.com/2026-02-01/share-secrets.json', {
method: 'POST',
headers: {
Authorization: 'Bearer ' + process.env.DONUTWORK_API_KEY,
'Content-Type': 'application/json',
},
body: JSON.stringify({
"shareSecret": {
"name": "Deployment API Token",
"content": "secret_value_redacted",
"requirePin": true,
"sendTo": {
"email": "engineer@partner-company.com",
"message": "The requested production API token is now available for one-time retrieval."
}
}
}),
});
const requestId = response.headers.get('x-request-id');
if (!response.ok) {
const error = await response.text();
throw new Error(`${response.status} ${error} [${requestId}]`);
}
const contentType = response.headers.get('content-type') ?? '';
const data = response.status === 204 ? null
: contentType.includes('application/json') ? await response.json()
: await response.text();$request = curl_init('https://api.hub.donutwork.com/2026-02-01/share-secrets.json');
curl_setopt_array($request, [
CURLOPT_CUSTOMREQUEST => 'POST',
CURLOPT_RETURNTRANSFER => true,
CURLOPT_HTTPHEADER => [
'Authorization: Bearer ' . getenv('DONUTWORK_API_KEY'),
'Content-Type: application/json',
],
CURLOPT_POSTFIELDS => '{
"shareSecret": {
"name": "Deployment API Token",
"content": "secret_value_redacted",
"requirePin": true,
"sendTo": {
"email": "engineer@partner-company.com",
"message": "The requested production API token is now available for one-time retrieval."
}
}
}',
]);
$response = curl_exec($request);
if ($response === false) {
$error = curl_error($request);
curl_close($request);
throw new RuntimeException($error);
}
$status = curl_getinfo($request, CURLINFO_RESPONSE_CODE);
$contentType = (string) curl_getinfo($request, CURLINFO_CONTENT_TYPE);
curl_close($request);
if ($status >= 400) { throw new RuntimeException($response); }
$data = $status === 204 ? null
: (str_contains($contentType, 'application/json')
? json_decode($response, true, flags: JSON_THROW_ON_ERROR) : $response);Replace uppercase placeholders and sample values with your own data and company resource IDs. Keep the API key on a trusted server. Reuse an idempotency key only for the same logical request and payload.
Technical Implementation
Access & Revocation
Audit Access Metadata
Retrieve the access status and reader telemetry for a specific secret link. This endpoint provides audit trails (IP, User-Agent, Timestamp) once the secret has been consumed.
share_secrets:readPath, query, and header parameters
secretIdRequiredResponses
Access metadata successfully retrieved.
{
"id": "6739782b...",
"name": "Database Migration Credentials",
"readed": true,
"readerInfo": {
"ip": "82.1.4.22",
"ua": "Mozilla/5.0...",
"isoDate": "03/03/2026 11:20:00",
"ts": 1772536800
}
}Request examples
curl --request GET 'https://api.hub.donutwork.com/2026-02-01/share-secrets/SECRETID.json' \
--header 'Authorization: Bearer YOUR_API_KEY'const response = await fetch('https://api.hub.donutwork.com/2026-02-01/share-secrets/SECRETID.json', {
method: 'GET',
headers: {
Authorization: 'Bearer ' + process.env.DONUTWORK_API_KEY,
},
});
const requestId = response.headers.get('x-request-id');
if (!response.ok) {
const error = await response.text();
throw new Error(`${response.status} ${error} [${requestId}]`);
}
const contentType = response.headers.get('content-type') ?? '';
const data = response.status === 204 ? null
: contentType.includes('application/json') ? await response.json()
: await response.text();$request = curl_init('https://api.hub.donutwork.com/2026-02-01/share-secrets/SECRETID.json');
curl_setopt_array($request, [
CURLOPT_CUSTOMREQUEST => 'GET',
CURLOPT_RETURNTRANSFER => true,
CURLOPT_HTTPHEADER => [
'Authorization: Bearer ' . getenv('DONUTWORK_API_KEY'),
],
]);
$response = curl_exec($request);
if ($response === false) {
$error = curl_error($request);
curl_close($request);
throw new RuntimeException($error);
}
$status = curl_getinfo($request, CURLINFO_RESPONSE_CODE);
$contentType = (string) curl_getinfo($request, CURLINFO_CONTENT_TYPE);
curl_close($request);
if ($status >= 400) { throw new RuntimeException($response); }
$data = $status === 204 ? null
: (str_contains($contentType, 'application/json')
? json_decode($response, true, flags: JSON_THROW_ON_ERROR) : $response);Replace uppercase placeholders and sample values with your own data and company resource IDs. Keep the API key on a trusted server. Reuse an idempotency key only for the same logical request and payload.
Revoke Secret Link
Manually revoke a secret link before it is consumed, or purge the audit record of an already read secret.
share_secrets:writePath, query, and header parameters
secretIdRequiredResponses
Secret link successfully revoked and record purged.
{
"id": "67397a4c...",
"deleted": true
}Request examples
curl --request DELETE 'https://api.hub.donutwork.com/2026-02-01/share-secrets/SECRETID.json' \
--header 'Authorization: Bearer YOUR_API_KEY'const response = await fetch('https://api.hub.donutwork.com/2026-02-01/share-secrets/SECRETID.json', {
method: 'DELETE',
headers: {
Authorization: 'Bearer ' + process.env.DONUTWORK_API_KEY,
},
});
const requestId = response.headers.get('x-request-id');
if (!response.ok) {
const error = await response.text();
throw new Error(`${response.status} ${error} [${requestId}]`);
}
const contentType = response.headers.get('content-type') ?? '';
const data = response.status === 204 ? null
: contentType.includes('application/json') ? await response.json()
: await response.text();$request = curl_init('https://api.hub.donutwork.com/2026-02-01/share-secrets/SECRETID.json');
curl_setopt_array($request, [
CURLOPT_CUSTOMREQUEST => 'DELETE',
CURLOPT_RETURNTRANSFER => true,
CURLOPT_HTTPHEADER => [
'Authorization: Bearer ' . getenv('DONUTWORK_API_KEY'),
],
]);
$response = curl_exec($request);
if ($response === false) {
$error = curl_error($request);
curl_close($request);
throw new RuntimeException($error);
}
$status = curl_getinfo($request, CURLINFO_RESPONSE_CODE);
$contentType = (string) curl_getinfo($request, CURLINFO_CONTENT_TYPE);
curl_close($request);
if ($status >= 400) { throw new RuntimeException($response); }
$data = $status === 204 ? null
: (str_contains($contentType, 'application/json')
? json_decode($response, true, flags: JSON_THROW_ON_ERROR) : $response);Replace uppercase placeholders and sample values with your own data and company resource IDs. Keep the API key on a trusted server. Reuse an idempotency key only for the same logical request and payload.
Security Policy: Content retrieval is handled via the specific url field returned during provisioning. Once the readed flag is set to true, the content is physically deleted from the database and cannot be recovered.