Every credential (API key or OAuth grant) carries three permission maps. Reads and writes are enforced against them. Admin credentials bypass all checks.Documentation Index
Fetch the complete documentation index at: https://docs.myme.so/llms.txt
Use this file to discover all available pages before exploring further.
The four maps
type_permissions
Controls read and write access to item types. Patterns support * wildcard and parent.* subtree matching.
core.bookmark.* beats *; core.bookmark.readwise beats core.bookmark.*.
Reads inherit down the type chain — read core.media returns core.media.* items (book, article, film, etc.). Writes don’t — writing to an inheriting type requires permission on the specific type. This prevents cross-app write-through on inheriting types.
extension_permissions
Controls which extension namespaces the credential can read or write. Extensions are not returned by default — a namespace must be explicitly permitted.
extension_permissions: {} cannot read or write any extension.
edge_permissions
Controls which edge types the credential can create, update, or delete.
edge_permissions: {} — edge access is opt-in; apps must declare each edge type they need.
metadata_permissions
Controls metadata-layer mutations that don’t fit the type / extension / edge axes — currently registering custom types via POST /types.
types (gates POST /types for non-admin credentials). New credentials default to metadata_permissions: {}.
OAuth tokens project the metadata.<sub>:<verb> scope into this map on the synthetic credential — a token granted metadata.types:write carries metadata_permissions: { types: "write" }. Admin credentials bypass.
The dual-gate rule
Edge writes require permission on both the source item’s type AND the edge type. Creating anabout edge from a core.note to a core.entity.person needs:
type_permissions: write oncore.note(the source item).edge_permissions: write onabout.
403 edge_permission_denied.
Admin credentials bypass both.
The rationale: an edge is a mutation of the source item’s graph view. Without type write, the app can’t mutate the item; adding an edge would be a back-door around that. Without edge write on the type, the app can’t create that kind of relationship — even if it owns the item.
Enforcement points
Enforcement by endpoint (quick reference)
Enforcement by endpoint (quick reference)
| Action | Checks |
|---|---|
GET /items?type=X | type_permissions[X]: read (or inheriting pattern) |
POST /items (create X) | type_permissions[X]: write |
PATCH /items/{id} (update X) | type_permissions[X]: write |
DELETE /items/{id} | type_permissions[X]: write |
POST /items/{id}/transition | type_permissions[X]: write |
POST /items with edges | type_permissions[X]: write AND edge_permissions[edge_type]: write per edge |
POST /edges | type_permissions[source.type]: write AND edge_permissions[edge_type]: write |
DELETE /edges/{id} | same as POST /edges |
PATCH /edges/{id} | same as POST /edges |
GET /items/{id}/extensions/{ns} | extension_permissions[ns]: read |
PUT /items/{id}/extensions/{ns} | extension_permissions[ns]: write |
Default tier on credentials
Credentials carry adefault_tier field — library or feed — that stamps the tier on items written by the credential when the client omits one. Clients can override per-write. There is no read-side tier-gate on the credential; tier filtering is a query concern (GET /items?tier=feed), not a permission boundary.
Patterns and practice
- A single app typically needs ~3–5 types and one extension namespace. A notes app might have
type: writeoncore.note,metadata: write,edge.about: write,edge.parent-of: write, andextension.notes-app.*: write. - Publishing destinations tend to be narrower than capture apps. A read-later service mostly writes
core.bookmark.*andcore.highlight; it needs edge write onreferences. - Start tight. It’s easier to add scopes than audit what’s actually in use later.
Revocation effect
Revoking a credential returns401 unauthorized on the next request. In-flight long-lived connections (SSE) terminate on the next heartbeat failure — there’s no active push. The audit trail captures the revocation event.