Squawk Secret API
Send first-time passwords automatically when your onboarding system creates a new account. Available on the Business plan.
How it works
When your system creates a new user (in Active Directory, Microsoft Entra, Google Workspace, or anywhere else), it calls the API with the new password, or asks us to generate one. We create a squawk, a one-time encrypted link, and can email it to the new person's personal address or their manager. The link is erased after it's opened. The API can never read a squawk's contents back, so a leaked key can't be used to collect passwords.
Authentication
Business owners and admins create API keys on the API page in Squawk Secret. Send the key in the Authorization header. Keys can be limited to specific networks and revoked anytime.
Authorization: Bearer sqs_your_key_here
Check a key:
curl https://www.squawksecret.com/api/v1/ping -H "Authorization: Bearer $SQUAWK_API_KEY"
Create a squawk
POST https://www.squawksecret.com/api/v1/squawks with a JSON body:
| Field | Description |
|---|---|
text | The password or message to send. Send this or generate_password. |
generate_password | true, or { "length": 24 } (12 to 64). We generate a strong password without look-alike characters and return it once in the response, so your system can set it on the account. |
email_to | Email addresses to send the link to (up to 20), for example the new hire's personal email. |
message | Optional note included in the email. |
sender_name | Name shown in the email. Defaults to your organization's name. |
expires_in_hours | 1 to 720. Default 72. Counted from opens_at if set. |
opens_at | Optional ISO date and time (up to 90 days ahead), like 2026-10-05T12:00:00Z. Until then the link shows a countdown and can’t be opened; nothing is used up. |
max_views | 1 to 100. Default 1. |
lock_to_emails | Only these addresses can open it; each must enter a code we email them. |
allowed_ips | Only open from these IP addresses or ranges. |
passphrase | A second secret the recipient must also enter. |
protect_view | true to turn on screenshot and copy deterrents. |
reference | Your own ID, such as the employee or ticket number (up to 200 characters). Returned in status and webhooks. |
Your organization's security policies apply to API requests too. Send an Idempotency-Key header so a retried request can't create a second squawk; a repeat within 24 hours returns 409 with the original id.
curl -X POST https://www.squawksecret.com/api/v1/squawks \
-H "Authorization: Bearer $SQUAWK_API_KEY" \
-H "Content-Type: application/json" \
-H "Idempotency-Key: onboard-jsmith" \
-d '{"generate_password": true, "email_to": ["jane.personal@example.com"], "reference": "EMP-1042", "message": "Your new work account is jsmith@yourcompany.com"}'
Response 201:
{
"id": "sqk_3f9a...",
"url": "https://www.squawksecret.com/s/...#...",
"expires_at": "2026-09-28T14:05:00.000Z",
"max_views": 1,
"reference": "EMP-1042",
"emailed": ["jane.personal@example.com"],
"email_errors": [],
"password": "k7Q!mR2x..."
}
The url and password are returned only in this response and are never stored in readable form.
Check status
GET https://www.squawksecret.com/api/v1/squawks/{id} returns status (scheduled, active, used, expired, or destroyed), opens_at, views, remaining_views, first_opened_at, last_opened_at, and your reference.
Destroy early
DELETE https://www.squawksecret.com/api/v1/squawks/{id} erases it immediately, for example if account creation failed or an offer was withdrawn.
Errors and limits
Errors return JSON like {"error": {"code": "policy_violation", "message": "..."}}. Codes include unauthorized, insufficient_scope, ip_not_allowed, invalid_request, policy_violation, duplicate_request, not_found, and rate_limited. Each key can make 120 requests per minute.
Security events for your SIEM
GET https://www.squawksecret.com/api/v1/events returns your organization’s audit trail as JSON, oldest first, for Splunk, Microsoft Sentinel, Datadog, Elastic, or any SIEM that polls an API. It needs a key with the events:read permission. It covers sign-ins and failed attempts, account and two-step changes, team, policy, API key, and billing changes, and squawk, request, Squawk Drop, and chat activity: who, what, when, and from where, never the contents of anything sent.
Parameters: after (continue after this event ID; use the next_after value from the previous page), since (an ISO time to start from), and limit (up to 1,000, default 100). The response is { "events": [...], "next_after": "...", "has_more": true }. Each event has id, time, event, category, outcome, actor, ip, user_agent, target, and details.
curl -H "Authorization: Bearer sqs_..." "https://www.squawksecret.com/api/v1/events?limit=500&after=0"
Prefer push? On the API page, Business owners and admins can send events as they happen to Splunk’s HTTP Event Collector or any HTTPS endpoint that accepts JSON.
Squawk Back: help desk identity checks
Start a Squawk Back check from your ticketing system or a script, then get the result by polling or by webhook. These are the same checks as the Squawk Back page: 6-digit codes that expire in 10 minutes with 5 tries, and the same rate limits. Use the person’s email or mobile number from your own records, never one the caller gives you. The key needs identity:write to start and complete checks, and identity:read to look them up.
POST https://www.squawksecret.com/api/v1/identity-checks with contact (an email address or US mobile number; required), direction (verify_them, the default: they read a code back to you or tap “Yes, it’s me”; or prove_us: they receive a code and you read the same code to them), and optionally name (the person), reference (your ticket number, up to 200 characters), and technician (the name shown to the person; without it, the message comes from your organization). For prove_us, the response includes the code to read aloud.
curl -X POST https://www.squawksecret.com/api/v1/identity-checks \
-H "Authorization: Bearer sqs_..." -H "Content-Type: application/json" \
-d '{"contact": "dana@example.com", "name": "Dana Lee", "reference": "TICKET-4821", "technician": "Sam"}'
GET https://www.squawksecret.com/api/v1/identity-checks/{id} returns status: pending, code_sent (prove_us), verified, not_verified (too many wrong codes), denied (the person said it wasn’t them: stop, someone may be impersonating them), expired, or cancelled, plus completed_via (code or button) and attempts_left. GET https://www.squawksecret.com/api/v1/identity-checks?reference=TICKET-4821 lists checks, optionally for one reference.
POST https://www.squawksecret.com/api/v1/identity-checks/{id}/code with {"code": "482913"} submits the code the person read to you; the response says whether it was accepted. POST .../{id}/cancel cancels a check. Contacts are always returned masked.
Requests: collect secrets and files, end to end
Ask someone to send you a password, document, or files through a one-time request link. Requests made through the API are always end to end: your system makes its own P-256 key pair and sends only the public key; responders’ browsers encrypt to it, and the API returns responses still encrypted, so only your system can open them (we can’t). The key needs requests:write to create and close requests, and requests:read to read them. Ready-to-use code for Node.js and Python is on the API page under Examples.
POST https://www.squawksecret.com/api/v1/requests with subject (required), public_key (required: your 65-byte uncompressed P-256 public key, base64url), and optionally message (instructions), expires_in_hours (1 to 8760; default 168), max_responses (1 to 1000; default 1), reference (your ticket number), and email_to (addresses to email the link to). It returns the request with its url to send the person.
curl -X POST https://www.squawksecret.com/api/v1/requests \
-H "Authorization: Bearer sqs_..." -H "Content-Type: application/json" \
-d '{"subject": "Your 2025 W-2", "public_key": "BHq...", "reference": "CASE-311", "email_to": ["dana@example.com"]}'
GET https://www.squawksecret.com/api/v1/requests/{id} returns status (open, full, expired, or closed) and the number of responses. GET https://www.squawksecret.com/api/v1/requests/{id}/responses returns each response’s one-time key (eph_pub), its encrypted text, and its files, whose encrypted bytes come from each file’s url. POST .../{id}/close closes the request and erases its responses, so fetch them first.
To decrypt a response: ECDH between your private key and eph_pub; HKDF-SHA256 with an empty salt and info sq2 req: followed by eph_pub, giving a 32-byte key; then AES-256-GCM with the given 12-byte IV, the 16-byte tag at the end of the ciphertext, and additional data sq2r:text for the text or sq2r:file: followed by the file’s n.
Squawk Drop: read what clients send, end to end
Pull the items clients send to your Squawk Drops into your own system, such as a document management or practice management system. Items come back exactly as the sender’s browser encrypted them, and your system decrypts them with the Squawk Drop’s own private key: the part after #2. in its recovery link (the Squawk Drop’s Settings, Copy recovery link). That key never passes through the API, so we still can’t read anything. Keep the recovery link only on the server that does the decrypting. The key needs drops:read to read, and drops:write to mark items done, erase them, or change approved senders. An API key acts for your whole organization, like an owner or admin, so it reaches every Squawk Drop. Ready-to-use code for Node.js and Python is on the API page under Examples.
GET https://www.squawksecret.com/api/v1/drops lists your Squawk Drops: id (such as drop_3), name (the web address name), title, url, public_key, who_can_send, max_upload_mb, and counts of new_items and done_items. Wherever a path below says {drop}, use either the id or the name.
GET https://www.squawksecret.com/api/v1/drops/{drop}/items returns items, newest first. Options: status (new, the default; done; or all), since (only items received after that time), and limit (up to 200). Each item has its id (the same drp_ id the webhook sends), sender_email, sender_verified, topic, received_at, erases_at, status, its one-time key eph_pub, the encrypted text and manifest, and files with each file’s index, size, number of pieces, and pieces_url. GET .../items/{id} returns one item.
curl "https://www.squawksecret.com/api/v1/drops/acme-tax/items?status=new" -H "Authorization: Bearer sqs_..."
Files are stored in encrypted 8 MB pieces. GET {pieces_url} returns short-lived download links for up to 64 pieces at a time (urls, valid for an hour), with pieces, piece_size, and next_from; pass ?from= that number for the next batch until it is null. The links go straight to storage and need no API key, so even a 10 GB file never passes through our servers. Items received before files were stored in pieces list them under legacy_files, each with a url that returns the encrypted bytes (IV in X-Squawk-IV).
To decrypt an item: take the private key from the recovery link (base64url PKCS#8, P-256); ECDH with the item’s eph_pub; HKDF-SHA256 with an empty salt and info sq2 req: followed by eph_pub, giving a 32-byte AES-256-GCM key. Every ciphertext ends with its 16-byte tag. The text uses its IV and additional data sq2r:text. The manifest uses its IV and additional data sq2box:manifest, and is a JSON list with each file’s name, type, size, and nonce, in file order. Piece i of file f uses an IV made of the file’s 8-byte nonce followed by i as a 4-byte big-endian number, and additional data sq2box:f:i:n, where n is the number of pieces; write the decrypted pieces out in order. A legacy file uses its IV and additional data sq2r:file: followed by its n.
POST .../items/{id}/done marks an item done (your team sees it as done by the API key’s name) and POST .../items/{id}/reopen puts it back to new. DELETE .../items/{id} erases an item and its files now, instead of at the end of the Squawk Drop’s retention period. GET https://www.squawksecret.com/api/v1/drops/{drop}/senders lists approved senders, and POST to the same address with add and remove (lists of email addresses, or @domain.com for everyone at a company) changes them, for example when a client is added in your CRM.
curl -X POST https://www.squawksecret.com/api/v1/drops/acme-tax/senders \
-H "Authorization: Bearer sqs_..." -H "Content-Type: application/json" \
-d '{"add": ["dana@example.com", "@newclient.com"]}'
Webhooks
Add an endpoint on the API page to be notified when a squawk is squawk.opened, squawk.expired, or squawk.destroyed, when a response arrives for a request (request.received, with the request’s id and reference; fetch the response through the API), when an item arrives in a Squawk Drop (squawkbox.received, with the item’s id, the Squawk Drop’s drop_id, drop name, and drop_title, the sender_email, topic, and number of files; fetch the item through the API), or when a Squawk Back check ends: identity.verified, identity.denied, or identity.failed (each with the check’s id, reference, masked contact, and status). Notices include the squawk id, your reference, and times, never the password or link. Each request carries a Squawk-Signature header, t=<unix time>,v1=<hex>, where v1 is an HMAC-SHA256 of <t>.<raw body> using your endpoint's signing secret. Reject requests older than 5 minutes.
// Node.js
const crypto = require('crypto');
function verify(rawBody, header, secret) {
const parts = Object.fromEntries(header.split(',').map((p) => p.split('=')));
if (Math.abs(Date.now() / 1000 - Number(parts.t)) > 300) return false;
const expected = crypto.createHmac('sha256', secret).update(parts.t + '.' + rawBody).digest('hex');
return crypto.timingSafeEqual(Buffer.from(expected), Buffer.from(parts.v1 || ''));
}
Squawk Links: short links and QR codes
Make short links and QR codes from your own system, such as one for every invoice or mailing, and read how often each was used. Needs an API key with links:write to create, change and delete, and links:read to read.
curl -X POST https://www.squawksecret.com/api/v1/links \
-H "Authorization: Bearer sqs_..." -H "Content-Type: application/json" \
-d '{"name": "Invoice 1042", "url": "https://example.com/pay/1042", "code": "inv-1042", "expires_at": "2027-01-31T17:00:00Z"}'
name and url are required. code chooses the ending (lower-case letters, numbers and hyphens, 3 to 40 characters); leave it out and one is made for you. expires_at is the moment the link stops working. The answer has the link’s id (such as lnk_812), the link to paste (counted as a click), the qr_link a QR code should hold (counted as a scan), and its state: active, paused, expired, or blocked.
GET https://www.squawksecret.com/api/v1/links lists your links, newest first (limit up to 200). GET https://www.squawksecret.com/api/v1/links/{id} returns one with its counts: total, qr_scans, link_clicks, and last_30_days. Wherever a path says {id}, the link’s ending works too. GET https://www.squawksecret.com/api/v1/links/{id}/qr.svg returns the QR code as an SVG picture in the link’s saved colors.
POST https://www.squawksecret.com/api/v1/links/{id} changes any of name, url, active (false pauses it), and expires_at (null clears it); the same link and printed code go to the new address right away. DELETE https://www.squawksecret.com/api/v1/links/{id} removes the link and its records for good. An organization can create 300 links an hour through the API.
Examples
PowerShell with Active Directory
$headers = @{ Authorization = "Bearer $env:SQUAWK_API_KEY"; "Idempotency-Key" = "onboard-$sam" }
$body = @{
generate_password = $true
email_to = @($personalEmail)
reference = $sam
message = "Your new account is $upn. You'll be asked to change this password at first sign-in."
} | ConvertTo-Json
$squawk = Invoke-RestMethod -Method Post -Uri "https://www.squawksecret.com/api/v1/squawks" -Headers $headers -ContentType "application/json" -Body $body
try {
New-ADUser -Name $displayName -SamAccountName $sam -UserPrincipalName $upn -Enabled $true -ChangePasswordAtLogon $true `
-AccountPassword (ConvertTo-SecureString $squawk.password -AsPlainText -Force)
} catch {
# Account creation failed: destroy the squawk so the link can't be used.
Invoke-RestMethod -Method Delete -Uri "https://www.squawksecret.com/api/v1/squawks/$($squawk.id)" -Headers @{ Authorization = "Bearer $env:SQUAWK_API_KEY" }
throw
}
Microsoft Power Automate or Entra lifecycle workflows
Add an HTTP action: Method POST, URI https://www.squawksecret.com/api/v1/squawks, headers Authorization: Bearer <your key> and Content-Type: application/json, and a body like the curl example with dynamic content for the email and reference. Add Parse JSON to use password and id in later steps. Store the key in Azure Key Vault or a secure input.
Zapier or Make
Trigger on your HR system's new-hire event (BambooHR, Rippling, Gusto, and others), then add Webhooks by Zapier: Custom Request (or Make's HTTP: Make a request) with method POST, the URL above, the Authorization header, and a JSON body.
Okta Workflows
Use the API Connector: Post card with the URL above, an Authorization header, and a JSON body built from the new user's attributes.
Questions
Email support@squawksecret.com.