<?xml version="1.0" encoding="UTF-8" ?>
<rss version="2.0" xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:slash="http://purl.org/rss/1.0/modules/slash/" xmlns:wfw="http://wellformedweb.org/CommentAPI/" xmlns:atom="http://www.w3.org/2005/Atom"><channel><title>Developer &amp;amp; Integration Help - Recent Threads</title><link>https://verint14-pre-03.socialedgeconsulting.io/product-fieldpulse/f/developer-integration-help</link><description /><dc:language>en-US</dc:language><generator>14.0.0.622 14</generator><lastBuildDate>Mon, 29 Sep 2025 11:47:00 GMT</lastBuildDate><atom:link rel="self" type="application/rss+xml" href="https://verint14-pre-03.socialedgeconsulting.io/product-fieldpulse/f/developer-integration-help" /><item><title>RE: Webhook payload structure for work_order.status_changed</title><link>https://verint14-pre-03.socialedgeconsulting.io/thread/962?ContentTypeID=1</link><pubDate>Mon, 29 Sep 2025 11:47:00 GMT</pubDate><guid isPermaLink="false">091ceb33-8b76-413d-8223-5d874f69cd96</guid><dc:creator>Devon Marsh</dc:creator><slash:comments>0</slash:comments><comments>https://verint14-pre-03.socialedgeconsulting.io/thread/962?ContentTypeID=1</comments><wfw:commentRss>https://verint14-pre-03.socialedgeconsulting.io/product-fieldpulse/f/developer-integration-help/168/webhook-payload-structure-for-work_order-status_changed/rss?ContentTypeId=0</wfw:commentRss><description>&lt;p&gt;Heads up: if you&amp;#39;re using the &lt;code&gt;work_order.status_changed&lt;/code&gt; event to trigger side effects (notifications, external syncs), watch out for rapid-fire status changes. We&amp;#39;ve seen cases where a bulk edit or script triggers &lt;code&gt;assigned&lt;/code&gt;→&lt;code&gt;in_progress&lt;/code&gt;→&lt;code&gt;on_hold&lt;/code&gt;→&lt;code&gt;in_progress&lt;/code&gt; within seconds. Your webhook handler needs to be idempotent or you&amp;#39;ll get race conditions.&lt;/p&gt;

&lt;p&gt;We ended up debouncing with a 5-second window keyed on &lt;code&gt;work_order_id&lt;/code&gt; + &lt;code&gt;changed_at&lt;/code&gt;. YMMV depending on your downstream systems.&lt;/p&gt;&lt;div style="clear:both;"&gt;&lt;/div&gt;</description></item><item><title>Webhook payload structure for work_order.status_changed</title><link>https://verint14-pre-03.socialedgeconsulting.io/thread/168?ContentTypeID=1</link><pubDate>Sun, 28 Sep 2025 15:15:00 GMT</pubDate><guid isPermaLink="false">5d8cbe91-a27a-4d70-938e-6297f07cb1ca</guid><dc:creator>Carlos Vega</dc:creator><slash:comments>5</slash:comments><comments>https://verint14-pre-03.socialedgeconsulting.io/thread/168?ContentTypeID=1</comments><wfw:commentRss>https://verint14-pre-03.socialedgeconsulting.io/product-fieldpulse/f/developer-integration-help/168/webhook-payload-structure-for-work_order-status_changed/rss?ContentTypeId=0</wfw:commentRss><description>&lt;p&gt;Need the exact payload structure for &lt;code&gt;work_order.status_changed&lt;/code&gt;. Docs show an example but no schema. Specifically:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Is &lt;code&gt;previous_status&lt;/code&gt; always present?&lt;/li&gt;
&lt;li&gt;What&amp;#39;s the timestamp format — ISO 8601 with millis or no?&lt;/li&gt;
&lt;li&gt;Are custom fields included or do I need a follow-up API call?&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Current handler is breaking on null &lt;code&gt;assignee_id&lt;/code&gt; when status goes from &lt;code&gt;assigned&lt;/code&gt; → &lt;code&gt;unassigned&lt;/code&gt;. Need to know what else can be null.&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;// What I&amp;#39;m receiving (sanitized):
{
  &amp;quot;event&amp;quot;: &amp;quot;work_order.status_changed&amp;quot;,
  &amp;quot;timestamp&amp;quot;: &amp;quot;2025-09-28T14:32:17.842Z&amp;quot;,
  &amp;quot;data&amp;quot;: {
    &amp;quot;work_order_id&amp;quot;: &amp;quot;wo_...&amp;quot;,
    &amp;quot;status&amp;quot;: &amp;quot;in_progress&amp;quot;,
    &amp;quot;previous_status&amp;quot;: &amp;quot;assigned&amp;quot;,
    &amp;quot;assignee_id&amp;quot;: &amp;quot;usr_...&amp;quot;,
    &amp;quot;changed_at&amp;quot;: &amp;quot;2025-09-28T14:32:15.000Z&amp;quot;
  }
}&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Show me the full schema or point me to OpenAPI/Swagger.&lt;/p&gt;&lt;div style="clear:both;"&gt;&lt;/div&gt;</description></item><item><title>RE: Webhook payload structure for work_order.status_changed</title><link>https://verint14-pre-03.socialedgeconsulting.io/thread/961?ContentTypeID=1</link><pubDate>Mon, 29 Sep 2025 09:15:00 GMT</pubDate><guid isPermaLink="false">7b4f7a5e-c62e-408f-92aa-69c1b8c3d0c2</guid><dc:creator>Eli Torres (Staff)</dc:creator><slash:comments>0</slash:comments><comments>https://verint14-pre-03.socialedgeconsulting.io/thread/961?ContentTypeID=1</comments><wfw:commentRss>https://verint14-pre-03.socialedgeconsulting.io/product-fieldpulse/f/developer-integration-help/168/webhook-payload-structure-for-work_order-status_changed/rss?ContentTypeId=0</wfw:commentRss><description>&lt;p&gt;Agreed on OpenAPI. Internal ticket is ENG-4421 — no ETA but it&amp;#39;s in the Q4 API polish backlog. I&amp;#39;ll poke the team.&lt;/p&gt;

&lt;p&gt;For now, here&amp;#39;s the validator I use internally (zod) if it helps:&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;const WebhookPayload = z.object({
  event: z.literal(&amp;#39;work_order.status_changed&amp;#39;),
  webhook_id: z.string(),
  timestamp: z.string().datetime(),
  data: z.object({
    work_order_id: z.string(),
    status: z.string(),
    previous_status: z.string().optional().nullable(),
    assignee_id: z.string().nullable(),
    team_id: z.string().nullable(),
    customer_id: z.string(),
    location_id: z.string().nullable(),
    scheduled_start: z.string().datetime().nullable(),
    scheduled_end: z.string().datetime().nullable(),
    changed_at: z.string().datetime(),
    changed_by: z.object({
      type: z.enum(['user', 'system', 'api']),
      id: z.string().nullable()
    })
  })
});&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;YMMV on the datetime validation — we include millis but not all parsers require them.&lt;/p&gt;&lt;div style="clear:both;"&gt;&lt;/div&gt;</description></item><item><title>RE: Webhook payload structure for work_order.status_changed</title><link>https://verint14-pre-03.socialedgeconsulting.io/thread/960?ContentTypeID=1</link><pubDate>Sun, 28 Sep 2025 17:31:00 GMT</pubDate><guid isPermaLink="false">6e253fa5-e52d-45eb-8efb-c3f67fa6e06e</guid><dc:creator>Carlos Vega</dc:creator><slash:comments>1</slash:comments><comments>https://verint14-pre-03.socialedgeconsulting.io/thread/960?ContentTypeID=1</comments><wfw:commentRss>https://verint14-pre-03.socialedgeconsulting.io/product-fieldpulse/f/developer-integration-help/168/webhook-payload-structure-for-work_order-status_changed/rss?ContentTypeId=0</wfw:commentRss><description>&lt;p&gt;@eli.torres thanks — null vs omitted was the issue. &lt;code&gt;previous_status&lt;/code&gt; missing on new WO caused my validator to throw.&lt;/p&gt;

&lt;p&gt;Confirmed &lt;code&gt;changed_by.type === &amp;quot;system&amp;quot;&lt;/code&gt; during automated status transitions (SLA breach auto-escalation). &lt;code&gt;id&lt;/code&gt; is null as expected.&lt;/p&gt;

&lt;p&gt;Still need that OpenAPI spec though. Maintaining hand-rolled validators is brittle.&lt;/p&gt;&lt;div style="clear:both;"&gt;&lt;/div&gt;</description></item><item><title>RE: Webhook payload structure for work_order.status_changed</title><link>https://verint14-pre-03.socialedgeconsulting.io/thread/959?ContentTypeID=1</link><pubDate>Sun, 28 Sep 2025 17:08:00 GMT</pubDate><guid isPermaLink="false">7a022678-0a04-4314-9a6a-59c3a04c0028</guid><dc:creator>Leo Nakamura</dc:creator><slash:comments>0</slash:comments><comments>https://verint14-pre-03.socialedgeconsulting.io/thread/959?ContentTypeID=1</comments><wfw:commentRss>https://verint14-pre-03.socialedgeconsulting.io/product-fieldpulse/f/developer-integration-help/168/webhook-payload-structure-for-work_order-status_changed/rss?ContentTypeId=0</wfw:commentRss><description>&lt;p&gt;Worth noting: &lt;code&gt;previous_status&lt;/code&gt; can also be &lt;code&gt;null&lt;/code&gt; (not just omitted) in legacy event streams. Defensive check:&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;const prev = payload.data.previous_status ?? null;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Also Setting Up Webhooks has outdated example — missing &lt;code&gt;changed_by&lt;/code&gt; entirely. Eli&amp;#39;s schema above matches prod.&lt;/p&gt;&lt;div style="clear:both;"&gt;&lt;/div&gt;</description></item><item><title>RE: Webhook payload structure for work_order.status_changed</title><link>https://verint14-pre-03.socialedgeconsulting.io/thread/958?ContentTypeID=1</link><pubDate>Sun, 28 Sep 2025 16:42:00 GMT</pubDate><guid isPermaLink="false">a9bc5ddb-08b9-454b-a832-9efe84453afd</guid><dc:creator>Eli Torres (Staff)</dc:creator><slash:comments>0</slash:comments><comments>https://verint14-pre-03.socialedgeconsulting.io/thread/958?ContentTypeID=1</comments><wfw:commentRss>https://verint14-pre-03.socialedgeconsulting.io/product-fieldpulse/f/developer-integration-help/168/webhook-payload-structure-for-work_order-status_changed/rss?ContentTypeId=0</wfw:commentRss><description>&lt;p&gt;Hey Carlos — yeah this one tripped me up too when I first looked at it. The docs example is incomplete and I keep meaning to push for a proper JSON Schema. Here&amp;#39;s what I can confirm from our side:&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Nullable fields (can be &lt;code&gt;null&lt;/code&gt; or omitted):&lt;/strong&gt;&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;code&gt;previous_status&lt;/code&gt; — omitted entirely on new work orders (no prior state)&lt;/li&gt;
&lt;li&gt;&lt;code&gt;assignee_id&lt;/code&gt; — null when unassigned&lt;/li&gt;
&lt;li&gt;&lt;code&gt;team_id&lt;/code&gt; — null when not assigned to a team&lt;/li&gt;
&lt;li&gt;&lt;code&gt;scheduled_start&lt;/code&gt; / &lt;code&gt;scheduled_end&lt;/code&gt; — null when no scheduling&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;Timestamp format:&lt;/strong&gt; Always ISO 8601 with milliseconds and Zulu offset (&lt;code&gt;2025-09-28T14:32:17.842Z&lt;/code&gt;). The &lt;code&gt;changed_at&lt;/code&gt; in your payload is the DB commit time; &lt;code&gt;timestamp&lt;/code&gt; is when we fired the webhook (usually 50–200ms later).&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Custom fields:&lt;/strong&gt; Not included in this event. You need to hit &lt;code&gt;GET /v1/work_orders/{id}&lt;/code&gt; with &lt;code&gt;?include=custom_fields&lt;/code&gt; if you need them. There&amp;#39;s a feature request to optionally include them in webhooks (API v2.1 added it for &lt;code&gt;work_order.created&lt;/code&gt; but not status changes yet).&lt;/p&gt;

&lt;p&gt;Full schema I&amp;#39;m aware of:&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;{
  &amp;quot;event&amp;quot;: &amp;quot;work_order.status_changed&amp;quot;,
  &amp;quot;webhook_id&amp;quot;: &amp;quot;wh_...&amp;quot;,
  &amp;quot;timestamp&amp;quot;: string,  // ISO 8601 with ms
  &amp;quot;data&amp;quot;: {
    &amp;quot;work_order_id&amp;quot;: string,
    &amp;quot;status&amp;quot;: string,           // new status
    &amp;quot;previous_status&amp;quot;: string?, // omitted if no prior
    &amp;quot;assignee_id&amp;quot;: string?,     // null if unassigned
    &amp;quot;team_id&amp;quot;: string?,         // null if no team
    &amp;quot;customer_id&amp;quot;: string,
    &amp;quot;location_id&amp;quot;: string?,
    &amp;quot;scheduled_start&amp;quot;: string?, // ISO 8601
    &amp;quot;scheduled_end&amp;quot;: string?,   // ISO 8601
    &amp;quot;changed_at&amp;quot;: string,       // when status actually changed
    &amp;quot;changed_by&amp;quot;: {             // user or system
      &amp;quot;type&amp;quot;: &amp;quot;user&amp;quot; | &amp;quot;system&amp;quot; | &amp;quot;api&amp;quot;,
      &amp;quot;id&amp;quot;: string?             // null for system
    }
  }
}&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;The &lt;code&gt;?&lt;/code&gt; denotes optional/nullable. Let me know if you&amp;#39;re seeing fields not in that list — we had a brief regression in August where &lt;code&gt;location_id&lt;/code&gt; was missing.&lt;/p&gt;&lt;div style="clear:both;"&gt;&lt;/div&gt;</description></item><item><title>RE: Using Make (Integromat) instead of Zapier — gotchas?</title><link>https://verint14-pre-03.socialedgeconsulting.io/thread/1016?ContentTypeID=1</link><pubDate>Fri, 26 Sep 2025 11:30:00 GMT</pubDate><guid isPermaLink="false">749e16d0-1775-4f54-802e-fb32a734ae3b</guid><dc:creator>Anita Sharma</dc:creator><slash:comments>0</slash:comments><comments>https://verint14-pre-03.socialedgeconsulting.io/thread/1016?ContentTypeID=1</comments><wfw:commentRss>https://verint14-pre-03.socialedgeconsulting.io/product-fieldpulse/f/developer-integration-help/180/using-make-integromat-instead-of-zapier-gotchas/rss?ContentTypeId=0</wfw:commentRss><description>&lt;p&gt;From a governance perspective, it is worth noting that Make&amp;#39;s data residency differs from Zapier. Make offers EU data residency; Zapier does not. If your organization has data localization requirements, this may influence platform selection regardless of functional considerations.&lt;/p&gt;
&lt;p&gt;Additionally, Make&amp;#39;s audit logging is more comprehensive — i.e., you can export execution logs via API, which may satisfy internal compliance requirements that Zapier&amp;#39;s dashboard-only logs do not meet.&lt;/p&gt;&lt;div style="clear:both;"&gt;&lt;/div&gt;</description></item><item><title>Using Make (Integromat) instead of Zapier — gotchas?</title><link>https://verint14-pre-03.socialedgeconsulting.io/thread/180?ContentTypeID=1</link><pubDate>Thu, 25 Sep 2025 13:30:00 GMT</pubDate><guid isPermaLink="false">72ea9936-27bb-47ab-9c85-5422eeaebd09</guid><dc:creator>Devon Marsh</dc:creator><slash:comments>5</slash:comments><comments>https://verint14-pre-03.socialedgeconsulting.io/thread/180?ContentTypeID=1</comments><wfw:commentRss>https://verint14-pre-03.socialedgeconsulting.io/product-fieldpulse/f/developer-integration-help/180/using-make-integromat-instead-of-zapier-gotchas/rss?ContentTypeId=0</wfw:commentRss><description>&lt;p&gt;Hey all — been using Zapier for a while but hit some limits on data transformation and branching logic. Looking at moving a few of our FieldPulse workflows over to Make (Integromat).&lt;/p&gt;
&lt;p&gt;Specifically wondering about:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Webhook payload differences — any fields that come through differently?&lt;/li&gt;
&lt;li&gt;Authentication refresh — does the OAuth token handling behave the same?&lt;/li&gt;
&lt;li&gt;Custom field values in triggers — I saw this thread about Zapier missing custom fields, curious if Make hits the same issue&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Also any general YMMV stuff — I&amp;#39;ve found Make&amp;#39;s error handling way more granular which is nice, but the FieldPulse module seems less polished than the Zapier one.&lt;/p&gt;
&lt;p&gt;What gotcha am I missing?&lt;/p&gt;&lt;div style="clear:both;"&gt;&lt;/div&gt;</description></item><item><title>RE: Using Make (Integromat) instead of Zapier — gotchas?</title><link>https://verint14-pre-03.socialedgeconsulting.io/thread/1015?ContentTypeID=1</link><pubDate>Fri, 26 Sep 2025 09:15:00 GMT</pubDate><guid isPermaLink="false">256f3561-0c9a-4c0a-a8a5-4a05c8b5587b</guid><dc:creator>Omar Hassan</dc:creator><slash:comments>0</slash:comments><comments>https://verint14-pre-03.socialedgeconsulting.io/thread/1015?ContentTypeID=1</comments><wfw:commentRss>https://verint14-pre-03.socialedgeconsulting.io/product-fieldpulse/f/developer-integration-help/180/using-make-integromat-instead-of-zapier-gotchas/rss?ContentTypeId=0</wfw:commentRss><description>&lt;p&gt;From a reliability perspective, Make&amp;#39;s error handling is indeed more granular — i.e., you can configure specific error routes per module rather than Zapier&amp;#39;s all-or-nothing approach.&lt;/p&gt;
&lt;p&gt;One edge case to consider: Make&amp;#39;s webhook module does not currently support signature verification out of the box (unlike Zapier&amp;#39;s &amp;quot;Webhooks by Zapier&amp;quot; which has a raw body option). If you need to verify the &lt;code&gt;X-FieldPulse-Signature&lt;/code&gt; header, you&amp;#39;ll need to use the HTTP module with &amp;quot;Get request headers&amp;quot; enabled, then run the HMAC verification in a Code module.&lt;/p&gt;
&lt;p&gt;Relevant for security posture if you&amp;#39;re processing sensitive work order data. The signature verification flow is documented in Setting Up Webhooks — worth implementing if this is customer-facing.&lt;/p&gt;&lt;div style="clear:both;"&gt;&lt;/div&gt;</description></item><item><title>RE: Using Make (Integromat) instead of Zapier — gotchas?</title><link>https://verint14-pre-03.socialedgeconsulting.io/thread/1014?ContentTypeID=1</link><pubDate>Thu, 25 Sep 2025 18:20:00 GMT</pubDate><guid isPermaLink="false">12fb1ad4-d143-40d2-aafc-645e5f0f592c</guid><dc:creator>Devon Marsh</dc:creator><slash:comments>0</slash:comments><comments>https://verint14-pre-03.socialedgeconsulting.io/thread/1014?ContentTypeID=1</comments><wfw:commentRss>https://verint14-pre-03.socialedgeconsulting.io/product-fieldpulse/f/developer-integration-help/180/using-make-integromat-instead-of-zapier-gotchas/rss?ContentTypeId=0</wfw:commentRss><description>&lt;p&gt;Perfect — the v1 vs v2 thing is exactly the kind of detail I needed. Already running into the &amp;quot;run it once to see data&amp;quot; pain, good to know that&amp;#39;s expected behavior and not me missing something.&lt;/p&gt;
&lt;p&gt;Will likely go HTTP module route for the newer endpoints. Appreciate the confirmation on OAuth refresh too.&lt;/p&gt;&lt;div style="clear:both;"&gt;&lt;/div&gt;</description></item><item><title>RE: Using Make (Integromat) instead of Zapier — gotchas?</title><link>https://verint14-pre-03.socialedgeconsulting.io/thread/1013?ContentTypeID=1</link><pubDate>Thu, 25 Sep 2025 16:45:00 GMT</pubDate><guid isPermaLink="false">772dc997-48aa-4aa3-b8a8-bb971b50f172</guid><dc:creator>Eli Torres (Staff)</dc:creator><slash:comments>0</slash:comments><comments>https://verint14-pre-03.socialedgeconsulting.io/thread/1013?ContentTypeID=1</comments><wfw:commentRss>https://verint14-pre-03.socialedgeconsulting.io/product-fieldpulse/f/developer-integration-help/180/using-make-integromat-instead-of-zapier-gotchas/rss?ContentTypeId=0</wfw:commentRss><description>&lt;p&gt;Devon — yeah this one tripped me up too when I first looked at it. Leo&amp;#39;s right on the custom fields thing, that&amp;#39;s a platform limitation on our end not a Zapier/Make thing.&lt;/p&gt;
&lt;p&gt;The OAuth refresh is actually &lt;em&gt;smoother&lt;/em&gt; in Make in my experience. Their &amp;quot;Connection&amp;quot; model handles token refresh automatically without the extra &amp;quot;Refresh Token&amp;quot; step you need in Zapier. Heads up though: if you&amp;#39;re using a custom OAuth app (not the default FieldPulse one in Make&amp;#39;s app directory), you&amp;#39;ll need to manually configure the token endpoint. That&amp;#39;s &lt;code&gt;&lt;a href="https://auth.fieldpulse.io/oauth/token"&gt;auth.fieldpulse.io/.../token&lt;/a&gt;&lt;/code&gt; with grant_type &lt;code&gt;refresh_token&lt;/code&gt;.&lt;/p&gt;
&lt;p&gt;One gotcha that got me: Make&amp;#39;s &amp;quot;FieldPulse&amp;quot; app in the directory is on v1 of our API. If you need v2 features (like the new checklist endpoints), use the generic HTTP module and hit the endpoints directly. The v1 app works fine for work orders and customers, just not the newer stuff.&lt;/p&gt;
&lt;p&gt;Also worth noting — Make doesn&amp;#39;t have the same &amp;quot;Test Trigger&amp;quot; behavior as Zapier. You often need to run the scenario once to see sample data, which can be annoying when you&amp;#39;re building against production. I usually set up a filter early in the scenario to catch only test records while I&amp;#39;m building.&lt;/p&gt;
&lt;p&gt;Documentation link for the direct API approach: Using the FieldPulse API&lt;/p&gt;&lt;div style="clear:both;"&gt;&lt;/div&gt;</description></item><item><title>RE: Using Make (Integromat) instead of Zapier — gotchas?</title><link>https://verint14-pre-03.socialedgeconsulting.io/thread/1012?ContentTypeID=1</link><pubDate>Thu, 25 Sep 2025 14:12:00 GMT</pubDate><guid isPermaLink="false">cab1dab8-61a8-48ac-92d2-ad7196c97b07</guid><dc:creator>Leo Nakamura</dc:creator><slash:comments>0</slash:comments><comments>https://verint14-pre-03.socialedgeconsulting.io/thread/1012?ContentTypeID=1</comments><wfw:commentRss>https://verint14-pre-03.socialedgeconsulting.io/product-fieldpulse/f/developer-integration-help/180/using-make-integromat-instead-of-zapier-gotchas/rss?ContentTypeId=0</wfw:commentRss><description>&lt;p&gt;Two things:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Webhook payloads are identical — same JSON structure. The difference is Make parses nested objects differently in the trigger data mapper. Check the &amp;quot;Data structure&amp;quot; settings on your webhook module.&lt;/li&gt;
&lt;li&gt;Custom fields: same limitation as Zapier. The &lt;code&gt;custom_fields&lt;/code&gt; array is not expanded in trigger payloads. You need a second API call to &lt;code&gt;/work_orders/{id}&lt;/code&gt; with &lt;code&gt;include=custom_fields&lt;/code&gt;.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;See Setting Up Webhooks — the payload examples there apply to both platforms.&lt;/p&gt;&lt;div style="clear:both;"&gt;&lt;/div&gt;</description></item><item><title>RE: Bulk work order import format specification</title><link>https://verint14-pre-03.socialedgeconsulting.io/thread/928?ContentTypeID=1</link><pubDate>Tue, 23 Sep 2025 14:55:00 GMT</pubDate><guid isPermaLink="false">cb042aca-6860-4b32-b812-443c700b305b</guid><dc:creator>Omar Hassan</dc:creator><slash:comments>0</slash:comments><comments>https://verint14-pre-03.socialedgeconsulting.io/thread/928?ContentTypeID=1</comments><wfw:commentRss>https://verint14-pre-03.socialedgeconsulting.io/product-fieldpulse/f/developer-integration-help/161/bulk-work-order-import-format-specification/rss?ContentTypeId=0</wfw:commentRss><description>&lt;p&gt;Excellent point regarding ambiguous references. I have confirmed that our customer dataset contains approximately 340 duplicate email records from legacy data quality issues. We will implement a pre-import deduplication pass.&lt;/p&gt;

&lt;p&gt;One additional observation: the &lt;code&gt;work_order_number&lt;/code&gt; field appears to enforce uniqueness at the account level, not merely within a given import batch. This is the expected behavior, I presume, but it was not explicitly documented. We have historical collisions where our legacy system&amp;#39;s sequence reset annually; we will need to namespace these (e.g., &lt;code&gt;WO-2019-0042&lt;/code&gt; → &lt;code&gt;MIG-2019-0042&lt;/code&gt;).&lt;/p&gt;&lt;div style="clear:both;"&gt;&lt;/div&gt;</description></item><item><title>Bulk work order import format specification</title><link>https://verint14-pre-03.socialedgeconsulting.io/thread/161?ContentTypeID=1</link><pubDate>Mon, 22 Sep 2025 14:00:00 GMT</pubDate><guid isPermaLink="false">316808ed-c464-4ef7-ac01-b9a492bed509</guid><dc:creator>Omar Hassan</dc:creator><slash:comments>6</slash:comments><comments>https://verint14-pre-03.socialedgeconsulting.io/thread/161?ContentTypeID=1</comments><wfw:commentRss>https://verint14-pre-03.socialedgeconsulting.io/product-fieldpulse/f/developer-integration-help/161/bulk-work-order-import-format-specification/rss?ContentTypeId=0</wfw:commentRss><description>&lt;p&gt;We are preparing to migrate approximately 12,000 historical work orders from our legacy system into FieldPulse. I have reviewed the Bulk Importing Inventory via CSV documentation, but I am seeking clarification on the specific schema requirements for work order imports, as the available documentation appears to focus on inventory rather than work order entities.&lt;/p&gt;

&lt;p&gt;Specifically, I would appreciate confirmation on the following points:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;&lt;strong&gt;Required vs. optional fields&lt;/strong&gt;: Which fields are mandatory for a successful import? I assume &lt;code&gt;work_order_number&lt;/code&gt;, &lt;code&gt;customer_id&lt;/code&gt; (or &lt;code&gt;customer_email&lt;/code&gt;), and &lt;code&gt;scheduled_date&lt;/code&gt; are required, but I would like explicit confirmation.&lt;/li&gt;

&lt;li&gt;&lt;strong&gt;Date/time formats&lt;/strong&gt;: The documentation references ISO 8601, but does not specify whether timezone offsets are supported (e.g., &lt;code&gt;2025-09-22T14:00:00-04:00&lt;/code&gt;) or if all timestamps must be normalized to UTC.&lt;/li&gt;

&lt;li&gt;&lt;strong&gt;Status mapping&lt;/strong&gt;: Our legacy system uses non-standard status values (e.g., &amp;quot;Dispatched,&amp;quot; &amp;quot;In Progress,&amp;quot; &amp;quot;Awaiting Parts&amp;quot;). Is there a defined mapping to FieldPulse&amp;#39;s internal status enum, or must we pre-transform these values?&lt;/li&gt;

&lt;li&gt;&lt;strong&gt;Technician assignment&lt;/strong&gt;: Can we assign technicians via &lt;code&gt;technician_email&lt;/code&gt; at import time, or does this require a separate API call post-import?&lt;/li&gt;

&lt;li&gt;&lt;strong&gt;Custom fields&lt;/strong&gt;: We have approximately 40 custom fields defined in our legacy system. Are these supported in the bulk import, and if so, what is the expected column naming convention (e.g., &lt;code&gt;custom_field_{id}&lt;/code&gt; or &lt;code&gt;cf_{name}&lt;/code&gt;)?&lt;/li&gt;

&lt;li&gt;&lt;strong&gt;Validation and error reporting&lt;/strong&gt;: Does the import process support partial success (i.e., importing valid rows while reporting errors for invalid rows), or is it atomic? What is the granularity of error reporting—row-level, field-level, or batch-level?&lt;/li&gt;

&lt;li&gt;&lt;strong&gt;Rate limiting and throughput&lt;/strong&gt;: Are there documented limits on import file size (rows or bytes) and concurrent import operations?&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;Additionally, I would like to understand whether there is a sandbox or staging environment where we can validate our transformation pipeline before performing the production import. Our migration window is constrained, and we would prefer to avoid iterative correction cycles against production data.&lt;/p&gt;

&lt;p&gt;I have attached a sample of our transformed data structure below for reference. Any clarification on the above points would be greatly appreciated.&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;work_order_number,customer_email,scheduled_date,status,technician_email,custom_field_site_id,custom_field_equipment_type
WO-2019-0042,customer@example.com,2019-03-15T09:00:00,Dispatched,tech@company.com,SITE-442,HVAC-Commercial&lt;/code&gt;&lt;/pre&gt;&lt;div style="clear:both;"&gt;&lt;/div&gt;</description></item><item><title>RE: Bulk work order import format specification</title><link>https://verint14-pre-03.socialedgeconsulting.io/thread/927?ContentTypeID=1</link><pubDate>Tue, 23 Sep 2025 11:28:00 GMT</pubDate><guid isPermaLink="false">b7c8c0cf-28d5-4c53-8908-9fa2cb49a78d</guid><dc:creator>Devon Marsh</dc:creator><slash:comments>1</slash:comments><comments>https://verint14-pre-03.socialedgeconsulting.io/thread/927?ContentTypeID=1</comments><wfw:commentRss>https://verint14-pre-03.socialedgeconsulting.io/product-fieldpulse/f/developer-integration-help/161/bulk-work-order-import-format-specification/rss?ContentTypeId=0</wfw:commentRss><description>&lt;p&gt;Heads up on a gotcha we hit: the importer validates customer existence by email at import time, but if you have &lt;strong&gt;duplicate customers&lt;/strong&gt; with the same email (e.g., from previous partial migrations or manual entry), the import will fail with &lt;code&gt;AMBIGUOUS_CUSTOMER_REFERENCE&lt;/code&gt; even though the email exists.&lt;/p&gt;

&lt;p&gt;We had to dedupe our customer base first. The API&amp;#39;s &lt;code&gt;/customers&lt;/code&gt; endpoint with &lt;code&gt;?email=&lt;/code&gt; returns all matches—worth checking programmatically before your import run.&lt;/p&gt;

&lt;p&gt;YMMV, but we ended up doing customer sync via API first, then using &lt;code&gt;customer_id&lt;/code&gt; in the work order import rather than email. Eliminated a whole class of reference errors.&lt;/p&gt;&lt;div style="clear:both;"&gt;&lt;/div&gt;</description></item><item><title>RE: Bulk work order import format specification</title><link>https://verint14-pre-03.socialedgeconsulting.io/thread/926?ContentTypeID=1</link><pubDate>Tue, 23 Sep 2025 08:12:00 GMT</pubDate><guid isPermaLink="false">a04e05a0-e046-454a-a40f-504c56872757</guid><dc:creator>Leo Nakamura</dc:creator><slash:comments>0</slash:comments><comments>https://verint14-pre-03.socialedgeconsulting.io/thread/926?ContentTypeID=1</comments><wfw:commentRss>https://verint14-pre-03.socialedgeconsulting.io/product-fieldpulse/f/developer-integration-help/161/bulk-work-order-import-format-specification/rss?ContentTypeId=0</wfw:commentRss><description>&lt;p&gt;Supplemental notes from a recent migration:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Custom field keys are case-sensitive and underscore-normalized. &amp;quot;Equipment Type&amp;quot; becomes &lt;code&gt;equipment_type&lt;/code&gt;, but if you created it as &amp;quot;Equipment-Type&amp;quot; originally, the key is &lt;code&gt;equipment_type&lt;/code&gt; anyway—hyphens become underscores. Verify in the UI.&lt;/li&gt;
&lt;li&gt;Technician email matching is case-insensitive but &lt;strong&gt;trailing-space sensitive&lt;/strong&gt;. Strip whitespace in your transform.&lt;/li&gt;
&lt;li&gt;Date parsing accepts &lt;code&gt;YYYY-MM-DD&lt;/code&gt; without time, assumes 00:00:00 in account timezone. We used this for historical jobs where exact time was lost.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Documentation gaps: Using the FieldPulse API has a more complete field reference than the import docs, oddly.&lt;/p&gt;&lt;div style="clear:both;"&gt;&lt;/div&gt;</description></item><item><title>RE: Bulk work order import format specification</title><link>https://verint14-pre-03.socialedgeconsulting.io/thread/925?ContentTypeID=1</link><pubDate>Mon, 22 Sep 2025 20:47:00 GMT</pubDate><guid isPermaLink="false">538376fc-268f-48b5-bf25-4b780b689d1b</guid><dc:creator>Eli Torres (Staff)</dc:creator><slash:comments>0</slash:comments><comments>https://verint14-pre-03.socialedgeconsulting.io/thread/925?ContentTypeID=1</comments><wfw:commentRss>https://verint14-pre-03.socialedgeconsulting.io/product-fieldpulse/f/developer-integration-help/161/bulk-work-order-import-format-specification/rss?ContentTypeId=0</wfw:commentRss><description>&lt;p&gt;Good catches.&lt;/p&gt;

&lt;p&gt;&lt;code&gt;on_hold&lt;/code&gt; is API/import-only by default. You can enable it in the UI under &lt;strong&gt;Settings → Work Orders → Status Configuration&lt;/strong&gt; by toggling &amp;quot;Show extended status set.&amp;quot; Without that, your ops team will see the order but can&amp;#39;t change status to or from &lt;code&gt;on_hold&lt;/code&gt;—it&amp;#39;ll display as &amp;quot;Unknown Status&amp;quot; which is... not ideal.&lt;/p&gt;

&lt;p&gt;Error format is semi-structured. The &lt;code&gt;__import_error&lt;/code&gt; column contains pipe-delimited codes and messages like this:&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;INVALID_CUSTOMER_EMAIL|No customer found with email &amp;#39;customer@example.com&amp;#39;
REQUIRED_FIELD_MISSING|scheduled_date is required
STATUS_INVALID|Value &amp;#39;Dispatched&amp;#39; is not a valid status; use &amp;#39;dispatched&amp;#39;&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;The prefix before the pipe is stable-ish—we don&amp;#39;t change them often, but they&amp;#39;re not formally versioned. If you&amp;#39;re building automated retry logic, I&amp;#39;d suggest parsing on the pipe and maintaining a lookup table rather than relying on position. The human-readable portion after the pipe occasionally gets tweaked for clarity.&lt;/p&gt;

&lt;p&gt;Yeah, I know &amp;quot;semi-structured&amp;quot; is frustrating. There&amp;#39;s an open ticket to expose proper JSON error arrays, but it&amp;#39;s behind some larger importer refactoring work. I&amp;#39;ll bump the thread with your use case—12,000 rows is exactly the scale where machine-readable errors matter.&lt;/p&gt;&lt;div style="clear:both;"&gt;&lt;/div&gt;</description></item><item><title>RE: Bulk work order import format specification</title><link>https://verint14-pre-03.socialedgeconsulting.io/thread/924?ContentTypeID=1</link><pubDate>Mon, 22 Sep 2025 18:15:00 GMT</pubDate><guid isPermaLink="false">e8992f6a-8fbf-4666-9afc-6ad0ed10e004</guid><dc:creator>Omar Hassan</dc:creator><slash:comments>0</slash:comments><comments>https://verint14-pre-03.socialedgeconsulting.io/thread/924?ContentTypeID=1</comments><wfw:commentRss>https://verint14-pre-03.socialedgeconsulting.io/product-fieldpulse/f/developer-integration-help/161/bulk-work-order-import-format-specification/rss?ContentTypeId=0</wfw:commentRss><description>&lt;p&gt;Thank you for the comprehensive response, Eli. This is precisely the level of detail I needed.&lt;/p&gt;

&lt;p&gt;A follow-up regarding the &lt;code&gt;on_hold&lt;/code&gt; status: I note that this status is not exposed in the standard UI dropdown for manual work order creation. Is this status accessible exclusively via import and API, or is there a configuration setting that enables it in the web interface? I want to ensure our operations team can subsequently manage these records without encountering unexpected visibility issues.&lt;/p&gt;

&lt;p&gt;Additionally, regarding the &lt;code&gt;__import_error&lt;/code&gt; column: is the error message format stable enough for programmatic parsing? Specifically, does it follow a structured format (e.g., JSON-encoded error objects, or machine-readable error codes), or is it free-form natural language intended solely for human review?&lt;/p&gt;&lt;div style="clear:both;"&gt;&lt;/div&gt;</description></item><item><title>RE: Bulk work order import format specification</title><link>https://verint14-pre-03.socialedgeconsulting.io/thread/923?ContentTypeID=1</link><pubDate>Mon, 22 Sep 2025 16:34:00 GMT</pubDate><guid isPermaLink="false">52d31b50-fdfc-4e15-a947-c14de78971db</guid><dc:creator>Eli Torres (Staff)</dc:creator><slash:comments>2</slash:comments><comments>https://verint14-pre-03.socialedgeconsulting.io/thread/923?ContentTypeID=1</comments><wfw:commentRss>https://verint14-pre-03.socialedgeconsulting.io/product-fieldpulse/f/developer-integration-help/161/bulk-work-order-import-format-specification/rss?ContentTypeId=0</wfw:commentRss><description>&lt;p&gt;Hey Omar, great questions—this is exactly the level of detail that makes migrations go smoothly. Let me work through these one by one.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Required fields&lt;/strong&gt;: You&amp;#39;ve got the core three right. Minimum viable row needs &lt;code&gt;work_order_number&lt;/code&gt;, &lt;code&gt;customer_email&lt;/code&gt; (&lt;code&gt;customer_id&lt;/code&gt; also works if you&amp;#39;ve already synced customers), and &lt;code&gt;scheduled_date&lt;/code&gt;. Everything else is optional, though I&amp;#39;d recommend including &lt;code&gt;status&lt;/code&gt; so you&amp;#39;re not left with 12,000 &amp;quot;Draft&amp;quot; orders to update later.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Date formats&lt;/strong&gt;: Timezone offsets are supported and encouraged—much better than assuming UTC and having 6am jobs show up at the wrong time. The parser handles both &lt;code&gt;2025-09-22T14:00:00-04:00&lt;/code&gt; and the Zulu format. If no offset is provided, it assumes the account&amp;#39;s configured timezone, which has caused some fun surprises in the past.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Status mapping&lt;/strong&gt;: This is where it gets tricky. FieldPulse&amp;#39;s internal enum is &lt;code&gt;draft&lt;/code&gt;, &lt;code&gt;scheduled&lt;/code&gt;, &lt;code&gt;dispatched&lt;/code&gt;, &lt;code&gt;in_progress&lt;/code&gt;, &lt;code&gt;completed&lt;/code&gt;, &lt;code&gt;cancelled&lt;/code&gt;, and &lt;code&gt;on_hold&lt;/code&gt;. Your &amp;quot;Dispatched&amp;quot; maps cleanly, &amp;quot;In Progress&amp;quot; → &lt;code&gt;in_progress&lt;/code&gt;, but &amp;quot;Awaiting Parts&amp;quot; doesn&amp;#39;t have a direct equivalent. Most folks map that to &lt;code&gt;on_hold&lt;/code&gt; with a note in the internal comments. There&amp;#39;s no automatic fuzzy matching—you&amp;#39;ll need to pre-transform.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Technician assignment&lt;/strong&gt;: Yes, &lt;code&gt;technician_email&lt;/code&gt; works at import time, but the technician needs to exist in the system first. The importer won&amp;#39;t auto-provision users. If you have multiple technicians per order, use &lt;code&gt;technician_emails&lt;/code&gt; (plural) with comma-separated values.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Custom fields&lt;/strong&gt;: Supported, but the naming convention is &lt;code&gt;custom_{field_key}&lt;/code&gt;, not ID-based. You can find the field keys under &lt;strong&gt;Settings → Custom Fields → Work Orders&lt;/strong&gt;—they&amp;#39;re the URL-safe slugs, not the display names. So if your field is named &amp;quot;Equipment Type,&amp;quot; the column might be &lt;code&gt;custom_equipment_type&lt;/code&gt; or &lt;code&gt;custom_equipment_type_2&lt;/code&gt; depending on duplicates.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Validation&lt;/strong&gt;: Partial success with row-level error reporting. You&amp;#39;ll get a downloadable CSV with an &lt;code&gt;__import_error&lt;/code&gt; column appended. Atomicity is per batch, and batches are chunked at 500 rows. So if row 501 fails, rows 1-500 still commit.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Limits&lt;/strong&gt;: 50,000 rows or 10MB per file, whichever comes first. No hard limit on concurrent imports, but we throttle to 2 per account to avoid database contention. If you need more throughput, open a ticket and we can coordinate.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Sandbox&lt;/strong&gt;: We don&amp;#39;t have a public sandbox environment for imports specifically, but I&amp;#39;d recommend creating a trial account under a different email domain for validation. The importer behaves identically, and you can blow it away after testing. Just don&amp;#39;t use your production customer/technician emails or you&amp;#39;ll get deduplication weirdness.&lt;/p&gt;

&lt;p&gt;Your sample looks structurally sound. One heads up: if that 2019 date is representative, check your account&amp;#39;s data retention settings—importing very old orders can trigger archival rules you weren&amp;#39;t expecting.&lt;/p&gt;

&lt;p&gt;Full schema reference is at Bulk Importing Inventory via CSV (yes, the work order section is buried in there—we&amp;#39;re fixing that). Also worth reading Duplicate Inventory Items Created During Import for common pitfalls that apply to work orders too.&lt;/p&gt;&lt;div style="clear:both;"&gt;&lt;/div&gt;</description></item><item><title>RE: Scope API key to read-only access</title><link>https://verint14-pre-03.socialedgeconsulting.io/thread/1036?ContentTypeID=1</link><pubDate>Sun, 21 Sep 2025 14:07:00 GMT</pubDate><guid isPermaLink="false">b2468ca8-fb58-4a47-9fce-0026e12e515a</guid><dc:creator>Leo Nakamura</dc:creator><slash:comments>0</slash:comments><comments>https://verint14-pre-03.socialedgeconsulting.io/thread/1036?ContentTypeID=1</comments><wfw:commentRss>https://verint14-pre-03.socialedgeconsulting.io/product-fieldpulse/f/developer-integration-help/184/scope-api-key-to-read-only-access/rss?ContentTypeId=0</wfw:commentRss><description>&lt;p&gt;Related: API key rotation with zero downtime covers automated rotation patterns.&lt;/p&gt;
&lt;p&gt;Also worth noting — the official Python SDK doesn&amp;#39;t expose the underlying HTTP status code cleanly on 403s. You&amp;#39;ll need to catch &lt;code&gt;FieldPulseAPIError&lt;/code&gt; and inspect &lt;code&gt;error.response.status_code&lt;/code&gt; manually.&lt;/p&gt;&lt;div style="clear:both;"&gt;&lt;/div&gt;</description></item><item><title>Scope API key to read-only access</title><link>https://verint14-pre-03.socialedgeconsulting.io/thread/184?ContentTypeID=1</link><pubDate>Sat, 20 Sep 2025 16:15:00 GMT</pubDate><guid isPermaLink="false">a90cd148-10db-4d3e-9b90-e80e55ecd821</guid><dc:creator>Rachel Nguyen</dc:creator><slash:comments>5</slash:comments><comments>https://verint14-pre-03.socialedgeconsulting.io/thread/184?ContentTypeID=1</comments><wfw:commentRss>https://verint14-pre-03.socialedgeconsulting.io/product-fieldpulse/f/developer-integration-help/184/scope-api-key-to-read-only-access/rss?ContentTypeId=0</wfw:commentRss><description>&lt;p&gt;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.&lt;/p&gt;
&lt;p&gt;I have reviewed the following documentation:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;API authentication overview (Using the FieldPulse API)&lt;/li&gt;
&lt;li&gt;User roles and permissions (Managing User Roles and Permissions)&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;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).&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Environment:&lt;/strong&gt;&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;FieldPulse account: Enterprise tier&lt;/li&gt;
&lt;li&gt;Current API key created: 2025-09-15&lt;/li&gt;
&lt;li&gt;Integration framework: Python 3.11, using official FieldPulse Python SDK v2.3.1&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&lt;strong&gt;Questions:&lt;/strong&gt;&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;Does FieldPulse support fine-grained API key permissions (read-only vs. read-write)?&lt;/li&gt;
&lt;li&gt;Is it possible to scope a key to specific endpoints or resource types?&lt;/li&gt;
&lt;li&gt;If not natively supported, what is the recommended pattern for achieving least-privilege access for automated read-only integrations?&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;I can reproduce the current full-access behavior consistently across all tested endpoints. Please advise on available configuration options.&lt;/p&gt;&lt;div style="clear:both;"&gt;&lt;/div&gt;</description></item><item><title>RE: Scope API key to read-only access</title><link>https://verint14-pre-03.socialedgeconsulting.io/thread/1035?ContentTypeID=1</link><pubDate>Sun, 21 Sep 2025 09:22:00 GMT</pubDate><guid isPermaLink="false">a2653dd7-a560-4513-a706-85ca0ea5ce27</guid><dc:creator>Fatima Al-Rashid</dc:creator><slash:comments>0</slash:comments><comments>https://verint14-pre-03.socialedgeconsulting.io/thread/1035?ContentTypeID=1</comments><wfw:commentRss>https://verint14-pre-03.socialedgeconsulting.io/product-fieldpulse/f/developer-integration-help/184/scope-api-key-to-read-only-access/rss?ContentTypeId=0</wfw:commentRss><description>&lt;p&gt;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:&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;API keys that are explicitly scoped at creation time, not merely restricted by runtime permissions&lt;/li&gt;
&lt;li&gt;Immutable audit trails of key creation and scope changes&lt;/li&gt;
&lt;li&gt;Automatic key expiration with rotation enforcement&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;It is also worth noting that the current FieldPulse API key model lacks:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Key expiration dates (keys are valid until manually revoked)&lt;/li&gt;
&lt;li&gt;Usage analytics or anomalous access detection&lt;/li&gt;
&lt;li&gt;IP allowlisting at the key level&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;For organizations with strict security requirements, I recommend implementing compensating controls:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Key rotation every 90 days via automated process&lt;/li&gt;
&lt;li&gt;Monitoring of all write operations via Audit Logs to detect any unexpected mutations&lt;/li&gt;
&lt;li&gt;Network-level restriction via egress filtering if your infrastructure supports it&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;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.&lt;/p&gt;&lt;div style="clear:both;"&gt;&lt;/div&gt;</description></item><item><title>RE: Scope API key to read-only access</title><link>https://verint14-pre-03.socialedgeconsulting.io/thread/1034?ContentTypeID=1</link><pubDate>Sat, 20 Sep 2025 19:15:00 GMT</pubDate><guid isPermaLink="false">24a2311a-09dc-471c-b8ad-34c2a6ae913a</guid><dc:creator>Eli Torres (Staff)</dc:creator><slash:comments>0</slash:comments><comments>https://verint14-pre-03.socialedgeconsulting.io/thread/1034?ContentTypeID=1</comments><wfw:commentRss>https://verint14-pre-03.socialedgeconsulting.io/product-fieldpulse/f/developer-integration-help/184/scope-api-key-to-read-only-access/rss?ContentTypeId=0</wfw:commentRss><description>&lt;p&gt;Awesome, glad that unblocked you. For the beta — shoot me a DM with your account ID and I&amp;#39;ll flag you for the early access list when we start private previews. Probably late Q4 2025.&lt;/p&gt;
&lt;p&gt;One heads up: the Viewer role blocking writes is Working As Intended&lt;span class="emoticon" data-url="https://verint14-pre-03.socialedgeconsulting.io/cfs-file/__key/system/emoji/2122.svg" title="Tm"&gt;&amp;#x2122;&lt;/span&gt; but not officially guaranteed behavior, since the API key itself still has &amp;quot;full&amp;quot; scope in a sense. I wouldn&amp;#39;t build critical security logic around it without monitoring. If someone accidentally bumps that service account to Manager, your sync suddenly has write access.&lt;/p&gt;
&lt;p&gt;Consider adding a cheap safety check in your Python wrapper — something like:&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;def validate_read_only(self, method):
    if method != &amp;#39;GET&amp;#39; and not self.allow_writes:
        raise ValueError(f&amp;quot;Read-only client rejected {method} request&amp;quot;)&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Defense in depth, etc etc.&lt;/p&gt;&lt;div style="clear:both;"&gt;&lt;/div&gt;</description></item><item><title>RE: Scope API key to read-only access</title><link>https://verint14-pre-03.socialedgeconsulting.io/thread/1033?ContentTypeID=1</link><pubDate>Sat, 20 Sep 2025 18:30:00 GMT</pubDate><guid isPermaLink="false">3d84d60d-b83e-4516-b9ec-34dc9523e0c8</guid><dc:creator>Rachel Nguyen</dc:creator><slash:comments>0</slash:comments><comments>https://verint14-pre-03.socialedgeconsulting.io/thread/1033?ContentTypeID=1</comments><wfw:commentRss>https://verint14-pre-03.socialedgeconsulting.io/product-fieldpulse/f/developer-integration-help/184/scope-api-key-to-read-only-access/rss?ContentTypeId=0</wfw:commentRss><description>&lt;p&gt;Thank you for the detailed response, Eli. I have confirmed that Option 1 works as described. I created a service account with the &amp;quot;Viewer&amp;quot; role and generated a new API key. I tested the following:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;code&gt;GET /v1/work_orders&lt;/code&gt; — returns 200 with expected payload&lt;/li&gt;
&lt;li&gt;&lt;code&gt;POST /v1/work_orders&lt;/code&gt; — returns 403 with message &amp;quot;User does not have permission to create work orders&amp;quot;&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;This satisfies our security requirements for the data warehouse sync. I will proceed with this configuration.&lt;/p&gt;
&lt;p&gt;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?&lt;/p&gt;&lt;div style="clear:both;"&gt;&lt;/div&gt;</description></item><item><title>RE: Scope API key to read-only access</title><link>https://verint14-pre-03.socialedgeconsulting.io/thread/1032?ContentTypeID=1</link><pubDate>Sat, 20 Sep 2025 17:42:00 GMT</pubDate><guid isPermaLink="false">8a26774a-8cc4-4425-a708-d20763c05a9b</guid><dc:creator>Eli Torres (Staff)</dc:creator><slash:comments>2</slash:comments><comments>https://verint14-pre-03.socialedgeconsulting.io/thread/1032?ContentTypeID=1</comments><wfw:commentRss>https://verint14-pre-03.socialedgeconsulting.io/product-fieldpulse/f/developer-integration-help/184/scope-api-key-to-read-only-access/rss?ContentTypeId=0</wfw:commentRss><description>&lt;p&gt;Hey Rachel — great question, and honestly this is something we could document better. Short answer: &lt;strong&gt;we don&amp;#39;t currently support fine-grained scopes on API keys&lt;/strong&gt;. A key is either valid (full access based on the account&amp;#39;s feature tier) or it&amp;#39;s not.&lt;/p&gt;
&lt;p&gt;The auth model right now is basically:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Your API key inherits the permissions of the user account that created it&lt;/li&gt;
&lt;li&gt;There&amp;#39;s no &amp;quot;read-only&amp;quot; key type or endpoint-level restrictions&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;That said, for your use case, here are the workarounds I see teams use:&lt;/p&gt;
&lt;h3&gt;Option 1: Service Account with Restricted User Role&lt;/h3&gt;
&lt;p&gt;Create a dedicated user account in FieldPulse with the &lt;strong&gt;Viewer&lt;/strong&gt; role (or custom role with &amp;quot;View&amp;quot; permissions only), then generate the API key from that account. The key will still &lt;em&gt;technically&lt;/em&gt; be able to call POST/PUT endpoints, but the underlying user permissions will block mutations. You&amp;#39;ll get 403s on write attempts, which is ... not elegant, but functional.&lt;/p&gt;
&lt;h3&gt;Option 2: Reverse Proxy with Request Filtering&lt;/h3&gt;
&lt;p&gt;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.&lt;/p&gt;
&lt;h3&gt;What we&amp;#39;re actually building&lt;/h3&gt;
&lt;p&gt;Scoped API keys with explicit read/write and resource-level permissions are on the roadmap for Q1 2026. I can&amp;#39;t share the full spec yet, but think along the lines of:&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;{
  &amp;quot;name&amp;quot;: &amp;quot;Data Warehouse Sync&amp;quot;,
  &amp;quot;scopes&amp;quot;: ["work_orders:read", "customers:read"],
  &amp;quot;allowed_ips&amp;quot;: ["10.0.0.0/8"]
}&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;No promises on exact syntax, but that&amp;#39;s the direction.&lt;/p&gt;
&lt;p&gt;For now, I&amp;#39;d recommend Option 1 — it&amp;#39;s what most of our Enterprise customers do for read-only ETL jobs. Want me to walk through setting up a restricted service account?&lt;/p&gt;&lt;div style="clear:both;"&gt;&lt;/div&gt;</description></item></channel></rss>