DocsGetting started

Integrations

Everything you need to call the ShareShield v2 API from a script or pipeline. For every endpoint and schema, see the API reference in the app.

Base URL
https://app.shareshield.net/api/v2
Auth
x-api-key header
Full reference
API v2 reference
Machine-readable
OpenAPI 3.1 spec
On this page
  1. API keys
  2. Your first call
  3. Scopes
  4. Using it from CI
  5. Errors
  6. Rate limits

API keys

Create a key in the app under Dashboard → Profile → API keys. A key:

  • looks like shs_ followed by 64 hex characters, and is shown once. ShareShield stores only a hash; the dashboard shows its prefix (for example shs_ab12cd34…) so you can tell keys apart;
  • is bound to one organisation, the one that was active when you created it, and stops working if its owner leaves that organisation;
  • is scoped: it can only do what its scopes allow, and never more than its owner's role allows;
  • can expire (after 1–365 days) and can be revoked at any time by its owner or an organisation admin. Expired and revoked keys get 401.

Keys can't manage the account: users, invitations, roles, settings, policies, SSO, billing and API keys themselves are only available to a signed-in session, so a leaked key can't mint new keys or invite anyone. Organisation admins can list and revoke every key in the organisation.

Your first call

Send the key in the x-api-key header. GET /api/v2/me tells you who the key belongs to:

Terminalbash
export SHARESHIELD_URL=https://app.shareshield.net
export SHARESHIELD_API_KEY=shs_…

curl -sS "$SHARESHIELD_URL/api/v2/me" -H "x-api-key: $SHARESHIELD_API_KEY"

Requests and responses are JSON (send content-type: application/json; file uploads are multipart/form-data). Lists are newest first and paginated with a cursor. Every response carries X-API-Version: 2.

Scopes

A key's permission is the intersection of its scopes and its owner's role. A scope never grants more than the role allows: a viewer's key can't create secrets even with secrets:create. New keys default to every scope your role allows; give integrations only the ones they need.

ScopeAllowsNeeds role permission
secrets:createCreate secrets and file secrets in the organization.secrets:create
secrets:readReveal (and so use a view of) a secret by its id.secrets:read
secrets:burnDestroy secrets the key owner created.secrets:create
secrets:listList metadata of the key owner's secrets (never their content).secrets:read
requests:createAsk someone to send you a secret.secrets:create
requests:readList the key owner's secret requests.secrets:read
audit:readRead the organization's audit log.audit:read

Owners and admins can use every scope; members every scope except audit:read; viewers secrets:read, secrets:list and requests:read.

Using it from CI

Store the key as a CI secret, ideally one with only secrets:create and an expiry. This GitHub Actions step sends a password to a colleague as a one-time, recipients-only link:

GitHub Actions stepyaml
- name: Send the staging database password to the on-call engineer
  env:
    SHARESHIELD_URL: https://app.shareshield.net
    SHARESHIELD_API_KEY: ${{ secrets.SHARESHIELD_API_KEY }}   # a key with only secrets:create
    DB_PASSWORD: ${{ secrets.STAGING_DB_PASSWORD }}
  run: |
    jq -n --arg content "$DB_PASSWORD" \
      '{content: $content, expiryHours: 4, maxViews: 1,
        recipients: ["[email protected]"], recipientsOnly: true}' \
    | curl -sS --fail-with-body -X POST "$SHARESHIELD_URL/api/v2/secrets" \
        -H "x-api-key: $SHARESHIELD_API_KEY" \
        -H "content-type: application/json" \
        --data @- \
    | jq '{expiresAt, recipients}'

The response includes the share link, but the step prints only the expiry and the per-address delivery report. Treat a share link like the secret itself and keep it out of build logs. Sending to recipients needs an authenticated caller and respects your organisation's recipient domain allow-list.

Errors

Errors always have the same shape. Branch on code, which is stable, rather than on the message:

Error responsejson
{
  "error": "Missing scope secrets:create",
  "code": "INSUFFICIENT_SCOPE",
  "details": { … }
}
StatusCodeMeaning
400VALIDATION_ERRORThe body or query failed validation (unknown fields included); details.issues lists each problem.
401UNAUTHORIZEDMissing, invalid, expired or revoked key.
402PAYMENT_REQUIREDOver a plan ceiling: monthly quota, expiry, views, or files on a plan without them. Upgrading fixes it.
403FORBIDDENThe owner's role or the organisation's policy does not allow it.
403INSUFFICIENT_SCOPEThe key lacks the scope the endpoint needs (details.requiredScope).
404NOT_FOUNDNo such secret or request.
410GONEAlready viewed, burned or expired.
415UNSUPPORTED_MEDIA_TYPEThe body is not application/json (or multipart/form-data for a file upload).
429TOO_MANY_REQUESTSRate limited; back off and retry later.

These are the common ones. The API reference lists every code, including those specific to files, recipients and requests, and the errors each endpoint can return.

Rate limits

Going over a limit returns 429 TOO_MANY_REQUESTS. Limits are counted in fixed windows shared by every app instance. The ones an integration is most likely to meet:

  • Revealing, downloading, checking and burning secrets: 30 attempts per IP per minute, shared.
  • Secret requests: 20 per user per hour and 100 per organisation per day.
  • Recipient emails: 100 recipients per user per hour and 500 per organisation per day.
  • Unknown links: an IP that tries 20 links that don't exist in an hour gets 429 on every lookup until the hour ends.

Separately, plan quotas and ceilings answer 402 and organisation policy ceilings 403. Call GET /api/v2/options to read the limits that apply to your key before you hit them.