</> PassIsland Developers API v1 Generate a token →

The PassIsland API

Everything a script or third-party tool can do on your behalf, using a personal access token instead of your master password. This is the reference for calling it directly — there's no SDK yet, just plain HTTP and JSON.

Base URL: https://api.passisland.replatform.co · every endpoint below is under /v1.

Quickstart

Two minutes from nothing to a working request.

  1. Generate a token

    Sign in to PassIsland, open Settings → Developer access, and generate one. Give it a label, pick the scopes it needs, and set an expiry. The full token — pisl_live_… — is shown exactly once, at creation. Store it like a password, because it effectively is one.

  2. Call an endpoint

    curl https://api.passisland.replatform.co/v1/account/me \
      -H "Authorization: Bearer pisl_live_..."
  3. That's the whole authentication story

    One header, no separate exchange step, no expiry to refresh day-to-day — a personal access token is a complete, self-contained credential. It's also, deliberately, not a way to sync vault data. See why below before you go looking for that endpoint.

The device-trust boundary

A personal access token has no device behind it, and vault access requires one.

PassIsland's vault sync isn't just password-protected — it's device-protected. A new device has to be individually approved by a device you already trust before it can pull vault ciphertext or key envelopes (that's the whole point of the "Approve this device" flow you see when you sign in somewhere new). That approval hands the new device a copy of your vault key, wrapped so only it can open it.

A personal access token can't participate in that ceremony — it's a string, not a device with a keypair — so it structurally cannot be handed a vault key. Rather than invent a "vault" scope and rely on nobody ever granting it by mistake, the vault routes (/v1/vaults/*) don't even parse a token-shaped credential: they only ever look for the session cookie a signed-in device carries. There is no misconfiguration that exposes vault content to a token, because the code path that reads a token isn't wired to those routes at all.

What's left — account info and device management — is exactly what's safe to automate: enough for a backup script to confirm your account is in good standing, or a security tool to revoke a lost laptop, without ever being able to read a single saved password.

Personal access tokens

Created and revoked from the web app only — POST /v1/tokens and DELETE /v1/tokens/:id both require a signed-in session, not another token. That's deliberate: a compromised token must not be able to mint itself a longer-lived replacement or a wider one.

Property
Formatpisl_live_ + 64 hex characters
LifetimeWhatever you set at creation — 30 days, 90 days, a year, or never (not recommended)
StorageOnly a SHA-256 hash is kept server-side. Lose the plaintext and the only fix is revoking it and creating a new one.
TransportAuthorization: Bearer pisl_live_.... Never a cookie, never a query parameter.
Server-side only. A personal access token authenticates as you with no further check — treat it like a password, not like a public API key. Never embed one in a browser bundle, a mobile app, or anything else you hand to someone else's machine. It also carries no CORS grant: api.passisland.replatform.co returns none, so a browser can't call it cross-origin even by accident.

Scopes

A token can carry any combination of these three — nothing more exists.

account:read — read /v1/account/me: email, verification status, member-since date. No password, no security answers.
devices:read — list your devices and their status via GET /v1/devices.
devices:manage — revoke or remove a device. Cannot approve a pending one — that step needs a trusted device's private key in hand, which no token ever has, so it's rejected outright rather than merely ungranted.

API reference

/v1/account

GET/v1/account/meaccount:read
{
  "accountId": "acct_...",
  "email": "you@example.com",
  "emailVerified": true,
  "status": "active",
  "hasVault": true,
  "entitlement": "free",
  "createdAt": "2026-01-14T09:02:11.000Z",
  "itemLimit": 5,
  "itemCount": 3,
  "adminRole": null
}

itemLimit is the maximum number of saved passwords this account may have at once — creating one more once itemCount reaches it is refused with 403 item_limit_reached until an old one is removed. adminRole is null for almost everyone; it reflects a role grant on the platform, not something this API lets you set.

/v1/devices

GET/v1/devicesdevices:read

Every device on the account — name, platform, status, last seen. Public keys are included; there is nothing secret in a device record.

POST/v1/devices/:id/revokedevices:manage

Ends that device's sessions immediately. Doesn't erase anything already cached on the device locally.

DELETE/v1/devices/:iddevices:manage

Removes a revoked (or never-approved) device from the list permanently. Refuses on an active device — revoke it first.

POST/v1/devices/:id/approvesession only

Rejected outright for a token, always — see why no vault scope. Approving a device needs the vault key in memory to wrap it for the new device.

/v1/tokens

GET/v1/tokenssession only

Your tokens' labels, scopes, and timestamps — never the value itself. There is no endpoint that returns a token's plaintext after creation.

POST/v1/tokenssession only

Create one. Returns the plaintext exactly this once.

{ "label": "backup script", "scopes": ["account:read"], "expiresInDays": 90 }
// → { "id": "pat_...", "token": "pisl_live_..." }
DELETE/v1/tokens/:idsession only

Revokes immediately. Anything using it starts failing with 401 unauthenticated on its very next call.

/v1/vaults — not reachable by token

Bootstrap, push/pull revisions, recovery, and the master-password change all live under /v1/vaults/*. They accept only the session cookie a signed-in device holds — a Bearer header is simply never inspected there. This isn't an authorization check that could be misconfigured; the routes and the token-resolving code aren't connected at all.

Errors

Every error is JSON: {"error": {"code": "...", "message": "..."}}.

StatusCodeMeaning
401unauthenticatedMissing, malformed, expired, or revoked token — or no session cookie for a session-only route.
403insufficient_scopeThe token is valid but doesn't carry the scope this endpoint needs.
403session_requiredThis action can only be done signed in — a token is refused outright, not just under-scoped.
403csrf_failedSession auth on a state-changing request without a valid CSRF token. Doesn't apply to token auth.
400invalid_requestMissing or wrong-shaped field — see the message for which.
404not_foundIncluding a token or device id that exists but belongs to someone else — never distinguished from "doesn't exist."
429rate_limitedToo many attempts in the current window. Back off and retry later.

Rate limits & security

  • A token's activity updates its "last used" timestamp on every successful call, visible next to it in Settings — the easiest way to notice one that's still active somewhere you didn't expect.
  • Revoking a token takes effect immediately and everywhere; there's no cache to wait out.
  • No CORS headers are returned by this API — it's server-to-server. A token belongs in a backend environment variable or secrets manager, never in code that ships to a browser.
  • Scopes are additive and capped at what exists today — account:read, devices:read, devices:manage. A vault-access scope isn't a future addition; see why no vault scope.
Report a vulnerability: email security@replatform.co. We'll acknowledge within a working day.