# Run Poller

> Trigger Orderful's inbound polling MapReduce in a NetSuite customer's account by calling the SuiteApp's run-poller RESTlet. Use when the user wants to manually pull pending inbound EDI transactions from Orderful into NetSuite without opening NetSuite to run the script deployment, or says things like "/run-poller", "run the poller for <customer>", "trigger inbound polling", "kick off the poller", "pull EDI transactions for <customer>", or "poll Orderful for <customer>".

- Skill: `orderful/run-poller` (Agent Skill, multi-file: 2 files)
- Install (CLI): `npx skillmds@latest add orderful/run-poller`
- Raw SKILL.md: https://api.skillmd.com/api/skills/orderful/run-poller/raw
- Safety review: pending
- Works with: Claude Code, Claude.ai, OpenAI Codex
- Category: Coding & Dev Tools
- Author: Orderful (https://skillmd.com/u/orderful)
- Updated: 2026-09-22
- Page: https://skillmd.com/skills/orderful/run-poller

---


# Run Inbound Poller

Triggers `customscript_orderful_inbound_mr` (the inbound polling MapReduce) in a customer's NetSuite by POSTing `{ "action": "triggerInboundPolling" }` to the SuiteApp's `customscript_orderful_agent_write_rl` RESTlet over TBA. The RESTlet is the generic Orderful Agent write surface; this skill exercises only its `triggerInboundPolling` action. Every agent-write request must also carry `authorizedBy` + `agentPlanId` — since v1.22 the RESTlet rejects the request *before* it dispatches on `action` without them. The script fills these from `AGENT_AUTHORIZED_BY` in the customer's `.env`, falling back to `cli:<os-user>`.

The polling MR pulls pending transactions from Orderful's polling bucket(s) into NetSuite. It runs on a 15-minute schedule by default; this skill is for ad-hoc triggers — after configuration changes, when debugging stuck transactions, during demos, or any time a contractor would otherwise open NetSuite to run the script deployment manually.

## When to use this skill

- "run the poller for cambridge-pavers"
- "I just changed the polling bucket — pull now"
- "trigger inbound polling for <customer>"
- "the customer says they're missing 850s — kick off the poller"
- "/run-poller"

## Inputs the skill needs

- **Customer slug** — which `~/orderful-onboarding/<slug>/` to use. Ask if not specified; list the available dirs.

That's it. The customer's `.env` (created by `/netsuite-setup`) supplies everything else.

## The recipe

### Step 1 — Pick the customer

List `~/orderful-onboarding/` and confirm which customer the user wants. If the dir has no `.env`, stop and direct the user to `/netsuite-setup`.

### Step 2 — Trigger the poller

Run the script:

```sh
node <path-to-this-skill>/run-poller.mjs ~/orderful-onboarding/<slug>
```

The script loads the customer's `.env`, picks `NS_SB_*` or `NS_PROD_*` based on `ENVIRONMENT`, TBA-signs a POST to the RESTlet URL with `{ "action": "triggerInboundPolling" }` as the body, and prints the response.

### Step 3 — Read the result

A successful response looks like:

```json
{
  "status": "success",
  "taskId": "MAPREDUCETASK_...",
  "mrStatus": {
    "type": "task.MapReduceScriptTaskStatus",
    "taskId": "MAPREDUCETASK_...",
    "scriptId": 546,
    "deploymentId": 4,
    "status": "PENDING",
    "stage": null
  },
  "scriptId": "customscript_orderful_inbound_mr",
  "deploymentId": "customdeploy_orderful_inbound_mr"
}
```

- `taskId` is the NetSuite task scheduler ID for the running MapReduce
- `mrStatus.status` will be `PENDING`, `PROCESSING`, `COMPLETE`, or `FAILED` — `PENDING`/`PROCESSING` is normal; the task continues server-side after this skill returns

To verify execution, hand the `taskId` to [monitor-mr](../monitor-mr/SKILL.md):

```bash
node skills/monitor-mr/monitor-mr.mjs <customer-dir> watch --flow inbound-polling --task <taskId>
```

It blocks until the task completes, surfaces the execution log (including the end-of-run SUMMARY with `mapErrors`/`reduceErrors`), and flags the chained processing run. Manual fallback: NetSuite UI **Customization > Scripting > Script Deployments > "Orderful | Polling Inbound Transactions" > Execution Log**.

Heads-up when verifying downstream: if the chained inbound-processing run shows `mapKeys: {}`, check whether the poll actually created OTs and whether they pass the pending-query filters — per source the ~10-minute freshness gate only bites around 00:00–00:10 account time, so it's rarely the reason (see [reference/mapreduce-monitoring.md](../../reference/mapreduce-monitoring.md)). To push one specific id through immediately, use [reprocess-transaction](../reprocess-transaction/SKILL.md). For after-the-fact "what did the scripts log about this transaction?", use [`which-script-ran`](../which-script-ran/SKILL.md).

### Required role permissions

The token's role needs all of these on **Setup > Users/Roles > Manage Roles > [role] > Permissions > Setup tab**:

- **Log in using Access Tokens** = Full
- **REST Web Services** = Full
- **SuiteScript** = Full *(executes the RESTlet itself)*
- **SuiteScript Scheduling** *(no level — just add the row; required because the RESTlet calls `task.create()` to submit the MapReduce)*

Administrator already has all four. Custom roles commonly ship with the first two but not the last two — that's the default failure mode for a fresh integration. See troubleshooting below for the specific error messages each missing permission produces.

### Step 4 — Troubleshoot if needed

| Symptom | Likely cause | Fix |
|---|---|---|
| 404 with `SSS_INVALID_SCRIPTLET_ID` (or older accounts: `INVALID_LOGIN_INVALID_SCRIPT_ID` / `INVALID_LOGIN_ATTEMPT`) on a `.env` already validated by `/netsuite-setup` | Customer's installed SuiteApp version is older than the agent-write RESTlet. | Upgrade the SuiteApp via `My SuiteApps` to the version that includes [NS-926](https://orderful.atlassian.net/browse/NS-926) ([netsuite-connector#758](https://github.com/Orderful/netsuite-connector/pull/758)); or fall back to running the MR manually (NetSuite UI: Customization > Scripting > Scheduled Script Status > New > pick `customscript_orderful_inbound_mr`) |
| `INVALID_LOGIN_ATTEMPT` *and* `/netsuite-setup` Step 5 also fails | Bad TBA credentials | Re-validate via `/netsuite-setup`; the Login Audit Trail diagnostic in that skill's Step 5 isolates which value is wrong |
| Response body contains `INSUFFICIENT_PERMISSION` with message *"You need the 'SuiteScript' permission..."* | Token's role is missing the **SuiteScript** permission | **Setup > Users/Roles > Manage Roles > [role] > Permissions > Setup tab** — add **SuiteScript** = `Full` |
| Response body contains `INSUFFICIENT_PERMISSION` with no specific permission named (or "You do not have permission to perform this operation") | Token's role can't submit MapReduce tasks via `task.create()` | **Setup > Users/Roles > Manage Roles > [role] > Permissions > Setup tab** — add **SuiteScript Scheduling** (no level selector — just add the row). Note: this is a different permission from "SuiteScript". Most custom roles need *both* |
| MR runs but processes 0 transactions | `custscript_orderful_polling_bucket` company-level script param is empty | Customization > Scripting > Scripts > "Orderful \| Polling Inbound Transactions" > Deployments > the deployment > script param values |

## Behaviour rules

1. **Never invoke the script without an explicit customer slug.** Ask the user which customer; don't pick one.
2. **Don't poll for completion in this skill.** The MR is asynchronous. Return the `taskId` and follow through with [monitor-mr](../monitor-mr/SKILL.md) (`watch --flow inbound-polling --task <taskId>`) for completion and output verification.
3. **If the endpoint 404s, do not retry or guess.** Report the version-mismatch fix from Step 4 and stop. Don't fall back silently to a different deploy ID.
4. **Don't assume sandbox vs. production.** The script reads `ENVIRONMENT` from the `.env`. If the user expected production but the env says sandbox (or vice versa), ask before changing.
5. **One customer per invocation.** No batch mode. Each customer's TBA token is per-account; running across multiple customers needs multiple invocations and is the user's call to make sequentially.
6. **Don't paste TBA secrets into chat.** Everything stays in the `.env`; the script reads it locally.

## Reference material

- `customscript_orderful_inbound_mr` (the MR being triggered) — defined in `Objects/customscript_orderful_inbound_mr.xml` in the [netsuite-connector](https://github.com/Orderful/netsuite-connector) repo
- The agent-write RESTlet (the endpoint this skill posts to): `FileCabinet/SuiteApps/com.orderful.orderfulnetsuite/ConfigAndUISupport/orderful_agentWrite_RL.ts` — introduced in [netsuite-connector#758](https://github.com/Orderful/netsuite-connector/pull/758) ([NS-926](https://orderful.atlassian.net/browse/NS-926)). Action used here: `triggerInboundPolling`
- Polling docs: [docs.orderful.com — inbound poller](https://docs.orderful.com/docs/inbound-poller)
- NetSuite `N/task` module: https://docs.oracle.com/en/cloud/saas/netsuite/ns-online-help/section_4623372451.html

