Scope API key to read-only access

We are implementing a data warehouse sync using the FieldPulse API and need to adhere to our internal least-privilege security policy. I have confirmed that the current API key we are using has full read/write access to all endpoints.

I have reviewed the following documentation:

  • API authentication overview (Using the FieldPulse API)
  • User roles and permissions (Managing User Roles and Permissions)

However, I cannot locate specific instructions for scoping an API key to read-only operations (GET requests only) or restricting access to specific resource types (e.g., work orders and customers only, excluding inventory modifications).

Environment:

  • FieldPulse account: Enterprise tier
  • Current API key created: 2025-09-15
  • Integration framework: Python 3.11, using official FieldPulse Python SDK v2.3.1

Questions:

  1. Does FieldPulse support fine-grained API key permissions (read-only vs. read-write)?
  2. Is it possible to scope a key to specific endpoints or resource types?
  3. If not natively supported, what is the recommended pattern for achieving least-privilege access for automated read-only integrations?

I can reproduce the current full-access behavior consistently across all tested endpoints. Please advise on available configuration options.

  • Hey Rachel — great question, and honestly this is something we could document better. Short answer: we don't currently support fine-grained scopes on API keys. A key is either valid (full access based on the account's feature tier) or it's not.

    The auth model right now is basically:

    • Your API key inherits the permissions of the user account that created it
    • There's no "read-only" key type or endpoint-level restrictions

    That said, for your use case, here are the workarounds I see teams use:

    Option 1: Service Account with Restricted User Role

    Create a dedicated user account in FieldPulse with the Viewer role (or custom role with "View" permissions only), then generate the API key from that account. The key will still technically be able to call POST/PUT endpoints, but the underlying user permissions will block mutations. You'll get 403s on write attempts, which is ... not elegant, but functional.

    Option 2: Reverse Proxy with Request Filtering

    Some teams put a lightweight proxy (nginx, AWS API Gateway, etc.) in front of our API that rejects anything except GET requests. Yeah, this is infrastructure you have to maintain, but it gives you surgical control.

    What we're actually building

    Scoped API keys with explicit read/write and resource-level permissions are on the roadmap for Q1 2026. I can't share the full spec yet, but think along the lines of:

    {
      "name": "Data Warehouse Sync",
      "scopes": ["work_orders:read", "customers:read"],
      "allowed_ips": ["10.0.0.0/8"]
    }

    No promises on exact syntax, but that's the direction.

    For now, I'd recommend Option 1 — it's what most of our Enterprise customers do for read-only ETL jobs. Want me to walk through setting up a restricted service account?

  • Thank you for the detailed response, Eli. I have confirmed that Option 1 works as described. I created a service account with the "Viewer" role and generated a new API key. I tested the following:

    • GET /v1/work_orders — returns 200 with expected payload
    • POST /v1/work_orders — returns 403 with message "User does not have permission to create work orders"

    This satisfies our security requirements for the data warehouse sync. I will proceed with this configuration.

    I have noted the Q1 2026 roadmap item — is there a public feature request or beta list we can join to track progress on scoped API keys?

  • Awesome, glad that unblocked you. For the beta — shoot me a DM with your account ID and I'll flag you for the early access list when we start private previews. Probably late Q4 2025.

    One heads up: the Viewer role blocking writes is Working As IntendedTm but not officially guaranteed behavior, since the API key itself still has "full" scope in a sense. I wouldn't build critical security logic around it without monitoring. If someone accidentally bumps that service account to Manager, your sync suddenly has write access.

    Consider adding a cheap safety check in your Python wrapper — something like:

    def validate_read_only(self, method):
        if method != 'GET' and not self.allow_writes:
            raise ValueError(f"Read-only client rejected {method} request")

    Defense in depth, etc etc.

  • From a governance perspective, it is worth noting that the workaround described above (using a restricted user role) does not satisfy all compliance frameworks that require cryptographic separation of privileges. In environments subject to SOC 2 Type II or ISO 27001 audits, auditor expectations typically include:

    1. API keys that are explicitly scoped at creation time, not merely restricted by runtime permissions
    2. Immutable audit trails of key creation and scope changes
    3. Automatic key expiration with rotation enforcement

    It is also worth noting that the current FieldPulse API key model lacks:

    • Key expiration dates (keys are valid until manually revoked)
    • Usage analytics or anomalous access detection
    • IP allowlisting at the key level

    For organizations with strict security requirements, I recommend implementing compensating controls:

    • Key rotation every 90 days via automated process
    • Monitoring of all write operations via Audit Logs to detect any unexpected mutations
    • Network-level restriction via egress filtering if your infrastructure supports it

    I have raised this topic with our CISO and would be interested in participating in any customer advisory sessions regarding the Q1 2026 scoped key feature.

  • Related: API key rotation with zero downtime covers automated rotation patterns.

    Also worth noting — the official Python SDK doesn't expose the underlying HTTP status code cleanly on 403s. You'll need to catch FieldPulseAPIError and inspect error.response.status_code manually.