Article Using the FieldPulse API

Using the FieldPulse API

So you want to build something with the FieldPulse API — cool. I've been down this road a few times (yeah, the OAuth flow tripped me up the first time too), and this doc should get you from zero to your first successful API call without too much head-scratching.

What You're Working With

The FieldPulse API is a RESTful JSON API. It's pretty standard stuff:

  • Base URL: https://api.fieldpulse.com/v2
  • Request format: JSON
  • Response format: JSON
  • Authentication: OAuth 2.0 with Bearer tokens

We rate limit at 100 requests per minute per token. Hit that and you'll get a 429 with a Retry-After header — more on that below.

Authentication: Getting Your Token

First things first — you need credentials. Head to Admin > API & Integrations in your FieldPulse account and generate an API key. You'll get a client_id and client_secret.

Here's the token exchange. This one's tripped up a lot of folks because the docs used to say grant_type=client_token which... nope, it's client_credentials.

POST https://auth.fieldpulse.com/oauth/token
Content-Type: application/x-www-form-urlencoded

grant_type=client_credentials
&client_id=YOUR_CLIENT_ID
&client_secret=YOUR_CLIENT_SECRET
&scope=work_orders:read work_orders:write customers:read

Response:

{
  "access_token": "eyJhbGciOiJSUzI1NiIs...",
  "token_type": "Bearer",
  "expires_in": 3600,
  "scope": "work_orders:read work_orders:write customers:read"
}

Heads up: That token expires in an hour. You'll want to refresh it before then — or just cache it and handle the 401 when it comes. In my experience, the latter is easier unless you're doing something real-time.

Making Your First Request

Once you've got your token, the rest is pretty straightforward. Let's grab a list of work orders:

GET https://api.fieldpulse.com/v2/work_orders?status=scheduled&limit=25
Authorization: Bearer eyJhbGciOiJSUzI1NiIs...
Accept: application/json

Response structure looks like this:

{
  "data": [
    {
      "id": "wo_abc123",
      "customer_id": "cust_xyz789",
      "status": "scheduled",
      "scheduled_start": "2026-04-15T09:00:00Z",
      "scheduled_end": "2026-04-15T11:00:00Z",
      "technician_ids": ["tech_001", "tech_002"],
      "location": {
        "address_line1": "123 Main St",
        "city": "Austin",
        "state": "TX",
        "postal_code": "78701"
      },
      "custom_fields": {
        "priority": "high",
        "equipment_type": "HVAC"
      }
    }
  ],
  "meta": {
    "total": 156,
    "page": 1,
    "per_page": 25,
    "has_more": true
  }
}

Note the meta object — you'll need that for pagination. More on that in a sec.

Common Patterns

Pagination

The API uses cursor-based pagination now (it used to be offset-based, which got slow at scale). Grab the next_cursor from meta and pass it as a query param:

GET /v2/work_orders?cursor=eyJpZCI6IndvX3h5ejk...&limit=25

Worth noting: If you're exporting a large dataset, expect this to take a few minutes. The API will happily serve you thousands of records, but don't hammer it with parallel requests — you'll hit rate limits fast.

Filtering

Most list endpoints support filtering by date range, status, and related IDs. The syntax is:

GET /v2/work_orders?status=completed&scheduled_after=2026-04-01T00:00:00Z&technician_id=tech_001

Date filters are inclusive of the start, exclusive of the end — yeah, I know, it's a bit weird. I actually filed a bug on this years ago and apparently it's "working as designed." So... plan accordingly.

Error Handling

The API returns consistent error shapes:

{
  "error": "validation_error",
  "message": "Invalid value for scheduled_start",
  "details": [
    {
      "field": "scheduled_start",
      "code": "invalid_format",
      "message": "Expected ISO 8601 datetime"
    }
  ]
}

Common status codes:

  • 400 — Bad request, check your JSON
  • 401 — Token expired or invalid
  • 403 — Your token doesn't have the right scope
  • 404 — Resource not found
  • 409 — Conflict (e.g., trying to modify a completed work order)
  • 429 — Rate limited, check Retry-After

Creating and Updating Records

POST and PATCH follow similar patterns. Here's creating a work order:

POST /v2/work_orders
Authorization: Bearer ...
Content-Type: application/json

{
  "customer_id": "cust_xyz789",
  "service_type": "maintenance",
  "scheduled_start": "2026-04-20T14:00:00Z",
  "scheduled_end": "2026-04-20T16:00:00Z",
  "technician_ids": ["tech_001"],
  "location": {
    "address_line1": "456 Oak Ave",
    "city": "Austin",
    "state": "TX"
  }
}

The response will include the created record with its generated id. If you need to assign multiple technicians, just add more IDs to that array — though heads up, there's a limit of 5 per work order.

Webhooks vs. Polling

If you're building something that needs to react to changes, don't poll. We have webhooks — see Setting Up Webhooks for the full setup. The short version: you can subscribe to events like work_order.created, work_order.status_changed, job.completed, etc.

Polling the API every few minutes for updates is... not great. You'll hit rate limits and your integration will be laggy. Use webhooks when you can.

Rate Limiting and Backoff

When you hit 429, back off exponentially. Something like:

const delay = Math.pow(2, retryCount) * 1000; // 1s, 2s, 4s, 8s...

Don't ignore the Retry-After header — it's there for a reason. And if you're doing bulk operations, consider using the Bulk Import API instead of hitting the regular endpoints hundreds of times.

SDKs and Tools

We don't have official SDKs (yet?), but the community has put together some solid options:

  • Node.js: fieldpulse-client on npm — unofficial but well-maintained
  • Python: There's a requests-based wrapper in the forums somewhere
  • Postman: Import our OpenAPI spec from https://api.fieldpulse.com/v2/openapi.json

For local webhook testing, ngrok is your friend. Or cloudflared tunnel if you're fancy.

Edge Cases That'll Get You

A few things I've personally stubbed my toe on:

  • Time zones: All datetimes in the API are UTC. Convert on your end.
  • Deleted records: We soft-delete. Check the deleted_at field — it might be non-null.
  • Custom fields: These vary by account. Query /v2/custom_fields first to see what's available.
  • Technician availability: The API won't stop you from double-booking — that's checked at scheduling time, not API validation time.

Getting Help

API questions can get technical fast. If you're stuck:

  • Check the API Rate Limits and Best Practices doc
  • Post in the Developers forum with your request ID (it's in the X-Request-ID response header)
  • For enterprise support, open a ticket through your account rep

And yeah — if something in this doc is wrong or out of date, let me know. The API changes sometimes and I don't always catch every update.

See Also

  • Setting Up Webhooks
  • API Rate Limits and Best Practices
  • Single Sign-On (SSO) Configuration
  • Discussion: Who's integrated FieldPulse with their CRM?