Permissions & Safety
Control access with permission tiers, constraints, and consent requirements.
paso provides multiple layers of safety to control what Claude can do with your API.
Permission Tiers
Every capability has a permission tier that determines who can call it.
read
Safe operations that don’t modify data. Examples: listing items, fetching details, searching.
- name: list_repos
description: List repositories
method: GET
path: /user/repos
permission: read
write
Operations that modify data but aren’t irreversible. Examples: creating items, updating fields, posting content.
- name: create_issue
description: Create an issue
method: POST
path: /repos/{owner}/{repo}/issues
permission: write
admin
High-risk operations that require explicit user approval. Examples: deleting resources, changing settings, transferring ownership.
- name: delete_repo
description: Delete a repository
method: DELETE
path: /repos/{owner}/{repo}
permission: admin
Consent Required
For sensitive operations, require the user to explicitly approve each call.
- name: create_issue
description: Create an issue in a repository
method: POST
path: /repos/{owner}/{repo}/issues
permission: write
consent_required: true
inputs:
- name: owner
type: string
required: true
- name: repo
type: string
required: true
- name: title
type: string
required: true
When consent_required: true, Claude will show a confirmation dialog before executing the tool.
Constraints
Limit resource usage and prevent abuse with constraints.
rate_limit
Maximum calls per minute.
- name: list_repos
description: List repositories
method: GET
path: /user/repos
permission: read
constraints:
rate_limit: 10
max_items
Maximum number of items returned in a single call.
- name: search_issues
description: Search for issues
method: GET
path: /search/issues
permission: read
constraints:
max_items: 50
max_value
Maximum numeric value allowed for an input.
- name: create_webhook
description: Create a webhook
method: POST
path: /repos/{owner}/{repo}/hooks
permission: write
inputs:
- name: timeout
type: number
description: Webhook timeout in seconds
constraints:
max_value: 300
required_with
Only allow this parameter if another parameter is present.
- name: update_user
description: Update a user
method: PATCH
path: /user
permission: write
inputs:
- name: email
type: string
- name: password
type: string
constraints:
required_with: email
Combining Constraints
Use multiple constraints together:
- name: list_events
description: List events with pagination
method: GET
path: /events
permission: read
inputs:
- name: limit
type: number
description: Number of events to return
constraints:
rate_limit: 5
max_items: 100
Forbidden List
Block entire paths or methods from being exposed.
forbidden:
paths:
- /admin/*
- /settings/billing
- /internal/*
methods:
- DELETE
Any capability that matches a forbidden path or method will not be exposed, even if declared.
Example: If /admin/* is forbidden, you cannot declare a capability with path /admin/users or /admin/settings.
Safety Best Practices
1. Start Conservative
Expose only what’s needed. It’s easier to add capabilities later than remove them.
# Good: minimal surface area
capabilities:
- name: list_repos
method: GET
path: /user/repos
permission: read
2. Use Permission Tiers
Assign the lowest permission tier appropriate for each operation.
# Good: read for safe queries
- name: get_repo
method: GET
path: /repos/{owner}/{repo}
permission: read
# Good: write for modifications
- name: update_repo
method: PATCH
path: /repos/{owner}/{repo}
permission: write
# Good: admin for deletion
- name: delete_repo
method: DELETE
path: /repos/{owner}/{repo}
permission: admin
3. Require Consent for Mutations
Any operation that creates or deletes should ask for approval.
- name: create_issue
permission: write
consent_required: true
- name: delete_issue
permission: admin
consent_required: true
4. Rate Limit Expensive Operations
Prevent resource exhaustion.
- name: generate_report
permission: read
constraints:
rate_limit: 1 # once per minute
5. Hide Admin Endpoints
Use the forbidden list to block sensitive paths.
forbidden:
paths:
- /admin/*
- /internal/*
- /settings/*
methods:
- DELETE
Real-World Example
Here’s a Stripe declaration with careful permission boundaries:
name: stripe-api
version: "1.0.0"
base_url: https://api.stripe.com/v1
auth:
type: basic
env_var: STRIPE_API_KEY
capabilities:
# Safe reads
- name: list_customers
description: List customers
method: GET
path: /customers
permission: read
constraints:
rate_limit: 10
- name: get_customer
description: Get customer details
method: GET
path: /customers/{customer_id}
permission: read
inputs:
- name: customer_id
type: string
required: true
# Modifications with consent
- name: create_customer
description: Create a new customer
method: POST
path: /customers
permission: write
consent_required: true
inputs:
- name: email
type: string
required: true
- name: update_customer
description: Update customer details
method: POST
path: /customers/{customer_id}
permission: write
consent_required: true
inputs:
- name: customer_id
type: string
required: true
# High-risk operations admin tier
- name: delete_customer
description: Delete a customer
method: DELETE
path: /customers/{customer_id}
permission: admin
consent_required: true
inputs:
- name: customer_id
type: string
required: true
# Block sensitive endpoints
forbidden:
paths:
- /account/*
- /applications/*
- /oauth/*
methods:
- DELETE
Your API is locked down.
Permission tiers, consent gates, constraints, and a forbidden list. Agents can only do what you allow.
Next, you might want to:
- Declarations — learn the full YAML format
- CLI Commands — test capabilities before deployment
- Testing Capabilities — safely preview requests