Skip to main content

overview

pipes can access the screenpipe API to read screen data, manage meetings, send notifications, and more. by default, pipes have full access to every endpoint — no restrictions. if you want to limit what a pipe can do, add a permissions block to the YAML frontmatter in pipe.md. this is useful for:
  • preventing accidents — a pipe that reads meetings shouldn’t be able to stop one
  • least privilege — pipes from the store should only access what they need
  • safety — deny destructive endpoints like /data/delete-range

quick start

---
schedule: every 30m
permissions: reader
---

Summarize my screen activity...
that’s it. this pipe can only read data — it can’t start/stop meetings, delete data, or run raw SQL.

presets

reader — safe read-only defaults

permissions: reader
allowed endpoints:
methodendpointdescription
GET/searchquery screen/audio data
GET/activity-summaryapp usage overview
GET/elementsUI element search
GET/frames/*screenshots (if allow_frames: true)
GET/meetingslist meetings
GET/meetings/*get meeting details
GET/meetings/statuscheck if in meeting
POST/notifysend notifications
GET/speakerslist speakers
POST/speakers/updateupdate speaker names
GET/pipes/infopipe metadata
GET/healthhealth check
GET/connections/*connection credentials
everything else is denied.

writer — reader + write operations

permissions: writer
includes all reader endpoints, plus:
methodendpointdescription
POST/meetings/startstart a manual meeting
POST/meetings/stopstop a manual meeting
PUT/meetings/*update meeting details
POST/meetings/mergemerge meetings
POST/memoriescreate memories
PUT/memories/*update memories
DELETE/memories/*delete memories

admin — full access (explicit)

permissions: admin
allows everything. functionally the same as no permissions block, but creates a token for logging/auditing.

custom rules

for fine-grained control, use allow and deny lists with Api(METHOD /path) patterns:
permissions:
  allow:
    - Api(GET /search)
    - Api(GET /meetings/*)
    - Api(POST /notify)
  deny:
    - Api(* /data/delete-*)

pattern syntax

patternmatches
Api(GET /search)exact: GET to /search
Api(GET /meetings/*)glob: GET to /meetings/42, /meetings/status, etc.
Api(* /meetings/stop)any method to /meetings/stop
Api(POST /notify)exact: POST to /notify
Api(* /data/*)any method to any /data/ subpath
* in the method position matches GET, POST, PUT, DELETE, etc. * in the path position matches any sequence of characters.

evaluation order

rules are evaluated in this order — first match wins:
  1. deny — if the request matches any deny rule, it’s blocked (403)
  2. allow — if the request matches any allow rule, it passes
  3. default allowlist — if allow is empty and the pipe uses a preset with defaults (reader/writer), the default list is checked
  4. reject — if nothing matched, the request is blocked
deny always wins over allow, just like firewall rules.

examples

deny specific endpoints (keep full access otherwise):
permissions:
  deny:
    - Api(* /meetings/stop)
    - Api(* /meetings/start)
    - Api(DELETE /meetings/*)
    - Api(* /data/delete-*)
allow only what you need (everything else denied):
permissions:
  allow:
    - Api(GET /search)
    - Api(POST /notify)
reader defaults + custom deny:
permissions:
  deny:
    - Api(GET /frames/*)
this uses the reader defaults but also blocks screenshot access.

data access rules

data filtering uses the same allow/deny lists with App(), Window(), and Content() rules:
---
schedule: every 1h
permissions:
  allow:
    - Api(GET /search)
    - App(Slack, Chrome)
    - Window(*meeting*)
    - Content(ocr, audio)
  deny:
    - App(1Password, Signal)
    - Window(*incognito*, *bank*)
    - Content(input)
  time: "09:00-17:00"
  days: "Mon,Tue,Wed,Thu,Fri"
---
rule typesyntaxdescription
App(name)App(Slack) or App(Slack, Chrome)filter by app name (case-insensitive substring match)
Window(glob)Window(*meeting*)filter by window title (glob pattern)
Content(type)Content(ocr, audio)filter content types: ocr, audio, input, accessibility
time"09:00-17:00"daily time window — supports midnight wrap ("22:00-06:00")
days"Mon,Tue,Wed,Thu,Fri"allowed days of the week
deny rules always win over allow rules. if no rules of a given type exist, everything is allowed.

how it works

when a pipe has any restrictions (permissions block, data filters, etc.):
  1. screenpipe generates a unique token (sp_pipe_*) for the pipe session
  2. the token is registered with the server middleware
  3. every API request from the pipe includes the token in Authorization: Bearer sp_pipe_*
  4. the middleware checks is_endpoint_allowed(method, path) before forwarding
  5. the Pi extension also enforces rules client-side (blocks curl commands before they run)
  6. when the pipe finishes, the token is cleaned up
pipes without any restrictions run without a token — full access, zero overhead.

common recipes

meeting-safe pipe

your pipe reads meeting data but should never interfere with active meetings:
---
schedule: every 1h
permissions:
  deny:
    - Api(* /meetings/start)
    - Api(* /meetings/stop)
    - Api(POST /meetings/merge)
    - Api(POST /meetings/bulk-delete)
    - Api(DELETE /meetings/*)
---

Summarize my meetings from the last hour...

read-only analytics pipe

---
schedule: daily
permissions:
  allow:
    - Api(GET /search)
    - App(Chrome, Arc, Firefox)
    - Content(ocr)
---

Generate a daily browsing report...

work-hours-only pipe

---
schedule: every 30m
permissions:
  time: "09:00-17:00"
  days: "Mon,Tue,Wed,Thu,Fri"
---

Track my work activity...
full API access, but time and day restrictions limit when data is visible. need help? ask in our discord