# Jev Bulk Classifier (TypeSafe AI System One) (`sameh.jarour/jev-classifier`) Actor

Bulk-classify texts or any Actor's dataset with TypeSafe AI's Jev: routing, sentiment, lead scoring and yes/no checks with calibrated confidence. Presets for Google Maps, LinkedIn, social media, reviews and job scrapers. Bring your own Jev key. $0.50 per 1,000 items.

- **URL**: https://apify.com/sameh.jarour/jev-classifier.md
- **Developed by:** [Sameh George Jarour](https://apify.com/sameh.jarour) (community)
- **Stats:** 2 total users, 1 monthly users, 0.0% runs succeeded, 0 bookmarks
- **User rating**: No ratings yet

## Pricing

$0.50 / 1,000 classified items

This Actor is paid per event. You are not charged for the Apify platform usage, but only a fixed price for specific events.

Learn more: https://docs.apify.com/actors/running/actors-in-store.md#pay-per-event

## What's an Apify Actor?

An Actor is a serverless cloud program that runs on the Apify platform. It has two run modes.
In Batch mode, an Actor accepts a well-defined JSON input, performs an action which can take anything from a few seconds to a few hours,
and optionally produces a well-defined JSON output, datasets with results, or files in key-value store.
In Standby mode, an Actor provides a web server which can be used as a website, API, or an MCP server.

Apify vocabulary and the platform model are defined once, in the agent quickstart at https://apify.com/agents.md.

## How to integrate an Actor?

If asked about integration, you help developers integrate Actors into their projects.
You adapt to their stack and deliver integrations that are safe, well-documented, and production-ready.

Do not guess an integration path. Every one of them is in the agent quickstart at https://apify.com/agents.md: the Apify MCP server, Agent Skills with the Apify CLI, the JavaScript and Python clients, the REST API, and the account-free path for an agent with no human to sign in. It also carries the rule on stating cost before the first paid run.

For examples already wired to this Actor's own input schema, see the [API](#api) section below.

Each client library has reference documentation the quickstart does not restate: [JavaScript/TypeScript](https://docs.apify.com/api/client/js/docs.md) (`npm install apify-client`) and [Python](https://docs.apify.com/api/client/python/docs.md) (`pip install apify-client`).

# README

### What does Jev Bulk Classifier do?

Jev Bulk Classifier is an **API wrapper for [TypeSafe AI's Jev](https://typesafe.ai)**, the first "System One" model. You give it a list of texts or JSON records and a set of typed questions, and it returns a **calibrated classification, score or yes/no probability for every item**. It is a fast, cheap alternative to prompting an LLM for classification: Jev returns typed decisions with confidence instead of free text, so there is nothing to parse and no hallucinated labels.

It does **not** generate text, summaries or code. Use it for triage, routing, tagging, sentiment and rubric scoring at scale.

Point it at the **dataset of any other Actor** (Google Maps Scraper, LinkedIn scrapers, Instagram or TikTok scrapers, Amazon Reviews Scraper, company enrichment tools) and pick a **ready-made question preset**, or paste your own items and questions.

### Why use Jev Bulk Classifier?

- ⚡ **Fast and cheap.** Jev answers in roughly 70–500 ms per item and charges $0.042 per million input tokens. Output tokens are free. Classifying 10,000 short support tickets with three questions costs well under a dollar in Jev tokens.
- 🎯 **Calibrated confidence.** Every answer carries probabilities and a confidence score, so you can auto-accept confident answers and route uncertain ones to a human.
- 🧩 **Three question types in one call.** Ask any mix of `choice`, `score` and `noul` (yes/no) questions. Jev evaluates all of them against each item in parallel, so extra questions cost tokens but almost no time.
- 🔗 **Works on other Actors' datasets.** Pass one or more dataset IDs, choose which fields to send, and every result row points back to the source dataset and offset.
- 🧠 **Presets for popular scrapers.** Google Maps reviews and places, LinkedIn profiles, company enrichment, social media posts and comments, product reviews, job postings, support tickets. Pick one and go.
- 🔁 **Bulk processing with retries.** Bounded concurrency, exponential backoff on rate limits, per-item error recording, and resume after platform migrations.
- ☁️ **Apify platform benefits.** Schedule runs, call it from the [API](https://docs.apify.com/api/v2), chain it after any scraper, export to CSV, Excel or JSON, and push results to Google Sheets, Slack or webhooks via [integrations](https://apify.com/integrations).

### What data does Jev Bulk Classifier output?

One dataset row per input item.

| Field | Type | Description |
| --- | --- | --- |
| `index` | integer | Position of the item in the combined list (inline items first, then dataset items). |
| `source` | object | `{type, datasetId, offset}`: where the item came from, for joining back to the source dataset. |
| `statePreview` | string | First 200 characters of the item. |
| `results` | object | Flat answer per question id: chosen label, expected score, or yes-probability. |
| `confidence` | object | Confidence 0–1 per question id. |
| `answers` | object | Raw Jev answers with full probability distributions and score legend. |
| `model` | string | Versioned model that answered, for example `jev-1.13.0`. |
| `inputTokens` | integer | Tokens billed by TypeSafe for this item. |
| `estimatedCostUsd` | number | `inputTokens × 0.042 / 1,000,000`. |
| `charged` | boolean | Whether the item was billed. Failed items are never charged. |
| `error` | object or null | Error class, HTTP status and message if the item failed. |

A `SUMMARY` record in the run's key-value store reports totals: items processed, succeeded, failed, total tokens and estimated Jev cost.

### How to classify texts with Jev

1. Get a TypeSafe AI API key at [console.typesafe.ai](https://console.typesafe.ai). Jev is currently in early access.
2. Open the Actor in Apify Console and paste the key into **TypeSafe AI API key**. It is stored encrypted and never written to logs.
3. Paste your **Items to classify**: a JSON array of strings or objects. Objects with named fields such as `{"subject": ..., "body": ...}` usually classify better than concatenated text.
4. Define your **Questions**. Each key is a question id and each value is a Jev question:
   - `choice` picks one label. `criteria` maps each label to a short description (up to 255 labels).
   - `score` rates against an ordered rubric. `criteria` is an array of 2–10 level descriptions from lowest to highest.
   - `noul` answers yes or no. `criteria` is optional and may describe the `true` and `false` outcomes.
5. Click **Start**. Watch the status line for progress, token usage and cost.
6. Open the **Output** tab or download the dataset. The `results` column gives you one value per question; `answers` has the full distributions.

### How to classify another Actor's dataset

1. Run any scraper, for example [Google Maps Reviews Scraper](https://apify.com/compass/google-maps-reviews-scraper), and copy its dataset ID from the run's Storage tab.
2. In this Actor, put the ID into **Dataset IDs**. You can list several.
3. Set **Dataset fields to send** to the fields Jev should read, for example `text, stars, title`. This matters: a full Google Maps place record can be thousands of tokens, while the review text is a few dozen. Dot notation such as `authorMeta.name` works. Items with none of the fields are skipped.
4. Pick a **Question preset** (table below) or write your own questions.
5. Optionally set **Max dataset items** to try the questions on a sample first.
6. Run. Each output row has `source.datasetId` and `source.offset`, so you can join `results` back to the original items, or simply export both datasets and merge on offset.

To automate this, add the classifier as the next step in an Apify integration or call it from the API with the finished run's `defaultDatasetId`.

### Question presets for popular scrapers

| Preset | Built for | Questions | Fields to send |
| --- | --- | --- | --- |
| `support-tickets` | Helpdesk exports, contact forms, inbound email | department (choice), frustration (score), is\_urgent (yes/no) | `subject, body` |
| `google-maps-reviews` | Google Maps Reviews Scraper, Google Maps Scraper reviews | sentiment (score), main\_topic (choice), is\_complaint, actionable\_feedback, would\_return | `text, stars, title` |
| `google-maps-leads` | Google Maps Scraper places, for outreach lists | business\_size (score), customer\_type (B2B/B2C), is\_independent, has\_website, online\_presence (score) | `title, categoryName, description, website, reviewsCount, totalScore` |
| `linkedin-profiles` | LinkedIn profile scrapers | seniority (choice), department (choice), is\_decision\_maker, is\_technical, open\_to\_opportunities | `headline, summary, jobTitle, companyName, experience` |
| `company-enrichment` | LinkedIn Company, Crunchbase, website scrapers | company\_size (score), business\_model (choice), sells\_to (B2B/B2C), is\_startup, is\_tech\_company | `name, description, industry, employeeCount, website` |
| `social-media-posts` | Instagram, TikTok, Facebook, X, YouTube post scrapers | sentiment (score), content\_type (choice), is\_sponsored, has\_call\_to\_action, is\_brand\_safe | `caption, text, hashtags` |
| `social-media-comments` | Comment scrapers for any network | sentiment (score), intent (choice), needs\_reply, is\_spam, is\_toxic | `text` |
| `product-reviews` | Amazon Reviews Scraper, e-commerce review scrapers | sentiment (score), main\_topic (choice), mentions\_defect, would\_recommend, is\_suspicious | `reviewTitle, reviewDescription, ratingScore` |
| `job-postings` | LinkedIn Jobs, Indeed and other job scrapers | seniority (choice), work\_arrangement (choice), employment\_type (choice), requires\_degree, salary\_disclosed, is\_technical\_role | `title, description, location, employmentType` |

Field names differ between scrapers; check one item of your dataset and adjust. A preset is a starting point: to change the labels or add a question, copy the preset's questions from the run log into the **Questions** field and switch the preset to *Custom*.

### How much does it cost to classify with Jev?

You pay two parties, and both charges are tiny:

- **Apify (this Actor)** bills **$0.50 per 1,000 classified items** ($0.0005 each) with pay-per-event pricing. Only items that Jev successfully classified are charged. Failed items, retries and the run itself are free. You can cap any run with **Maximum cost per run** in the run options; the Actor stops cleanly when the cap is reached, keeps every result produced so far, and tells you how many items are left.
- **TypeSafe AI** bills Jev tokens to your own key at $0.042 per million input tokens. A 300-token message with the three example questions uses about 470 input tokens, or roughly $0.00002. Ten thousand such items cost about $0.20. Output tokens are free.

So classifying 10,000 support tickets with three questions costs about $5 on Apify plus $0.20 on TypeSafe. The `SUMMARY` record and the per-item `estimatedCostUsd` and `charged` fields report actual usage, so you never have to guess.

### Input

See the **Input** tab for all options. Minimal example:

```json
{
    "apiKey": "YOUR_TYPESAFE_API_KEY",
    "items": [
        "Hi, I've been trying to connect my Stripe account for 3 days and the integration keeps failing. I'm losing sales. Please help ASAP.",
        { "subject": "Invoice question", "body": "Can you send me the invoice for August? No rush." },
        "How much does the enterprise plan cost for 50 seats?"
    ],
    "questions": {
        "department": {
            "type": "choice",
            "instructions": "Which team should handle this message?",
            "criteria": {
                "billing": "Payments, invoicing, refunds, subscription charges",
                "technical": "Bugs, outages, integrations, errors",
                "sales": "Pricing, upgrades, new accounts, plan questions"
            }
        },
        "frustration": {
            "type": "score",
            "instructions": "How frustrated does the customer appear?",
            "criteria": ["Calm, just stating facts", "Frustrated but civil", "Very angry, strong language"]
        },
        "is_urgent": {
            "type": "noul",
            "instructions": "Does the message convey urgency or time-sensitivity?",
            "criteria": { "true": "Explicitly time-sensitive or blocking", "false": "No urgency expressed" }
        }
    }
}
```

Dataset example with a preset:

```json
{
    "apiKey": "YOUR_TYPESAFE_API_KEY",
    "datasetIds": ["Sn7qAbnhkKIzqlJRa"],
    "datasetFields": ["text", "stars", "title"],
    "preset": "google-maps-reviews",
    "maxItems": 500
}
```

Optional fields: `preset` (default `custom`), `datasetFields`, `maxItems` (default 0 = all), `model` (`jev-latest`, `jev-preview` or a pinned version such as `jev-1.13.0`), `concurrency` (default 10), `maxRetries` (default 5), `requestTimeoutSecs` (default 60), `failOnError` (default false) and `includeRawResponse` (default false). When a preset is selected, the `questions` field is ignored.

The `questions` object is passed to Jev unchanged, so anything the [TypeSafe API reference](https://docs.typesafe.ai/api) accepts works here. The Actor validates the structure before spending any tokens and reports the exact field that is wrong.

### Output

You can download the dataset in various formats such as JSON, CSV, Excel or HTML. In CSV and Excel exports, nested fields flatten to columns such as `results.department` and `confidence.is_urgent`.

Successful item:

```json
{
    "index": 0,
    "source": { "type": "inline", "offset": 0 },
    "statePreview": "Hi, I've been trying to connect my Stripe account for 3 days and the integration keeps failing. I'm losing sales. Please help ASAP.",
    "results": { "department": "technical", "frustration": 1.0, "is_urgent": 0.98 },
    "confidence": { "department": 0.95, "frustration": 1.0, "is_urgent": 0.98 },
    "answers": {
        "department": { "type": "choice", "choice": "technical", "confidence": 0.95, "probabilities": { "technical": 0.97, "sales": 0.0, "billing": 0.03 } },
        "frustration": { "type": "score", "score": 1.0, "confidence": 1.0, "legend": { "0": "Calm, just stating facts", "1": "Frustrated but civil", "2": "Very angry, strong language" }, "probabilities": { "0": 0.0, "1": 1.0, "2": 0.0 } },
        "is_urgent": { "type": "noul", "noul": 0.98 }
    },
    "model": "jev-1.13.0",
    "inputTokens": 472,
    "outputTokens": 73,
    "estimatedCostUsd": 0.000019824,
    "durationMs": 412,
    "charged": true,
    "error": null
}
```

Failed item (run continues unless `failOnError` is on):

```json
{
    "index": 7,
    "source": { "type": "dataset", "datasetId": "Sn7qAbnhkKIzqlJRa", "offset": 4 },
    "statePreview": "...",
    "results": {},
    "confidence": {},
    "answers": {},
    "model": null,
    "inputTokens": null,
    "estimatedCostUsd": null,
    "durationMs": 31250,
    "charged": false,
    "error": { "type": "RateLimitError", "status": 429, "message": "429 Too Many Requests", "retryable": true, "requestId": "req_01..." }
}
```

### Tips for better Jev classifications

- **Describe every option.** Jev reads the `criteria` descriptions literally. Two or three concrete phrases per label beat a single word.
- **Put shared context in `instructions`, not in each item.** Instructions are sent with every call anyway, and keeping items short lowers token cost.
- **Use structured items.** An object such as `{"subject": ..., "body": ..., "customer_tier": ...}` lets you ask questions about specific fields.
- **Threshold on `confidence`.** Auto-apply answers above 0.9 and queue the rest for review. Pin a versioned model such as `jev-1.13.0` once you tune thresholds so results stay stable.
- **Turn up concurrency for big batches.** Jev allows roughly 1,200 requests per minute. Concurrency 20–30 is fine for short items; if you see `RateLimitError` rows, lower it or raise `maxRetries`.
- **Chain Actors.** Run a scraper first, then pass its dataset ID in `datasetIds`. Always set `datasetFields`; whole scraper records are large and Jev only needs the text.

### Limitations

- **Text only.** No images, audio or video.
- **No generation.** Jev never writes text; it only picks, scores or judges.
- **Literal reading.** Negations and scoping words are taken at face value. It does not count, do arithmetic or compare dates as quantities.
- **One item per call.** There is no batch endpoint, so cost scales with items × tokens. All questions for an item share one call.
- **Size limits.** Up to 255 choice options, 2–10 score levels, ~32k tokens per item plus the longest question, 64k tokens total per call.
- **Untrusted input can steer answers.** Jev does not treat item text as hostile. If items come from end users, keep decision-critical rules in `instructions`.

### FAQ

#### Is my TypeSafe API key safe?

Yes. The `apiKey` field is a secret input: Apify stores it encrypted, masks it in the Console and the Actor never logs it. Logging goes through Apify's logger, which additionally censors credential-like strings. The key is used only to call `api.typesafe.ai`.

#### Why did the run fail with a 422 or 400 error?

Jev rejected the request structure, almost always because of the `questions` definition: a `choice` without `criteria`, a `score` with fewer than two levels, or an unknown `type`. The Actor validates these locally first, so a 422 that gets through usually means a field Jev supports that the local check does not know about. The error message names the exact field path.

#### Why is confidence low?

Low confidence means the probability mass is spread across options. Usually the option descriptions overlap or the item genuinely fits several labels. Sharpen the descriptions, split ambiguous labels, or add a `noul` question that isolates the ambiguous property.

#### Can I use this without an Apify account?

No. The Actor runs on the Apify platform. You do need your own TypeSafe AI key; the Actor never uses a shared key.

#### What happens to my data?

Items are sent to TypeSafe AI for evaluation and results are stored in your Apify dataset under your account's retention settings. Do not send personal or sensitive data unless you have a lawful basis to process it and have reviewed TypeSafe AI's terms. You are responsible for the content you classify.

### Support

Found a bug or want another preset? Open a ticket in the **Issues** tab. For programmatic use, see the **API** tab, which shows ready-made code for Node.js, Python and curl.

# Actor input Schema

## `apiKey` (type: `string`):

Your TypeSafe AI (Jev) API key from <a href='https://console.typesafe.ai' target='_blank'>console.typesafe.ai</a>. Stored encrypted and never logged. You pay TypeSafe directly for Jev tokens. For local development you can omit it and set the <code>JEV\_API\_KEY</code> or <code>TYPESAFE\_API\_KEY</code> environment variable instead.

## `items` (type: `array`):

Texts or JSON objects to evaluate, one Jev call per item. Each item may be a plain string (e.g. a support message) or a JSON object/array (e.g. <code>{"subject": ..., "body": ...}</code>). Leave empty when you use <b>Dataset IDs</b> instead.

## `datasetIds` (type: `array`):

IDs or names of Apify datasets whose items should be classified, for example the default dataset of a Google Maps Scraper run. Items are processed after any inline <b>Items</b>. Each output row records the source dataset and offset so you can join results back.

## `datasetFields` (type: `array`):

Only these fields of each dataset item are sent to Jev (dot notation such as <code>authorMeta.name</code> works). Strongly recommended for large records like Google Maps places: it cuts token cost and keeps Jev focused. Leave empty to send whole items. Items with none of the fields are skipped.

## `maxItems` (type: `integer`):

Stop loading dataset items after this many (across all datasets). 0 means no limit. Handy for testing questions on a sample before a full run.

## `preset` (type: `string`):

Ready-made question sets for the outputs of popular scrapers. Pick one and you can leave <b>Questions</b> untouched; choose <i>Custom</i> to use your own questions below. See the README for what each preset asks and which dataset fields to send.

## `questions` (type: `object`):

Used when <b>Question preset</b> is <i>Custom</i>. Map of question id → Jev question, passed to the API verbatim. Types: <b>choice</b> (<code>criteria</code> = object mapping option label → description, up to 255 options), <b>score</b> (<code>criteria</code> = ordered array of 2–10 level descriptions), <b>noul</b> (yes/no; optional <code>criteria</code> with <code>true</code>/<code>false</code> descriptions).

## `model` (type: `string`):

Jev model or alias. <code>jev-latest</code> is the stable release alias. Pin a versioned id if you have tuned confidence thresholds and want answers to stay stable across releases.

## `concurrency` (type: `integer`):

Number of items evaluated in parallel. Jev allows roughly 1,200 requests per minute; 10 is safe for most accounts. Raise it for large batches of short items.

## `maxRetries` (type: `integer`):

Retries on rate limits (429), overload (529), other 5xx, timeouts and connection errors, with exponential backoff that honors Retry-After. Invalid key (401) and malformed requests (400/422) are never retried.

## `requestTimeoutSecs` (type: `integer`):

Timeout per HTTP attempt. Typical Jev calls finish in well under a second; raise this only for very large items.

## `failOnError` (type: `boolean`):

If enabled, the first item that still fails after retries aborts the whole run. If disabled (default), the error is recorded in the item's <code>error</code> field and processing continues. An invalid API key always aborts the run.

## `includeRawResponse` (type: `boolean`):

Adds the complete Jev response as <code>rawResponse</code> on every dataset item, in addition to the normalized <code>results</code>, <code>confidence</code> and <code>answers</code> fields.

## Actor input object example

```json
{
  "items": [
    "Hi, I've been trying to connect my Stripe account for 3 days and the integration keeps failing. I'm losing sales. Please help ASAP.",
    {
      "subject": "Invoice question",
      "body": "Can you send me the invoice for August? No rush."
    },
    "How much does the enterprise plan cost for 50 seats?"
  ],
  "maxItems": 0,
  "preset": "custom",
  "questions": {
    "department": {
      "type": "choice",
      "instructions": "Which team should handle this message?",
      "criteria": {
        "billing": "Payments, invoicing, refunds, subscription charges",
        "technical": "Bugs, outages, integrations, errors",
        "sales": "Pricing, upgrades, new accounts, plan questions"
      }
    },
    "frustration": {
      "type": "score",
      "instructions": "How frustrated does the customer appear?",
      "criteria": [
        "Calm, just stating facts",
        "Frustrated but civil",
        "Very angry, strong language"
      ]
    },
    "is_urgent": {
      "type": "noul",
      "instructions": "Does the message convey urgency or time-sensitivity?",
      "criteria": {
        "true": "Explicitly time-sensitive or blocking",
        "false": "No urgency expressed"
      }
    }
  },
  "model": "jev-latest",
  "concurrency": 10,
  "maxRetries": 5,
  "requestTimeoutSecs": 60,
  "failOnError": false,
  "includeRawResponse": false
}
```

# Actor output Schema

## `classifications` (type: `string`):

No description

## `summary` (type: `string`):

No description

# API

You can run this Actor programmatically using our API. Below are code examples in JavaScript, Python, and CLI, as well as the OpenAPI specification and MCP server setup.

## JavaScript example

```javascript
import { ApifyClient } from 'apify-client';

// Initialize the ApifyClient with your Apify API token
// Replace the '<YOUR_API_TOKEN>' with your token
const client = new ApifyClient({
    token: '<YOUR_API_TOKEN>',
});

// Prepare Actor input
const input = {
    "items": [
        "Hi, I've been trying to connect my Stripe account for 3 days and the integration keeps failing. I'm losing sales. Please help ASAP.",
        {
            "subject": "Invoice question",
            "body": "Can you send me the invoice for August? No rush."
        },
        "How much does the enterprise plan cost for 50 seats?"
    ],
    "questions": {
        "department": {
            "type": "choice",
            "instructions": "Which team should handle this message?",
            "criteria": {
                "billing": "Payments, invoicing, refunds, subscription charges",
                "technical": "Bugs, outages, integrations, errors",
                "sales": "Pricing, upgrades, new accounts, plan questions"
            }
        },
        "frustration": {
            "type": "score",
            "instructions": "How frustrated does the customer appear?",
            "criteria": [
                "Calm, just stating facts",
                "Frustrated but civil",
                "Very angry, strong language"
            ]
        },
        "is_urgent": {
            "type": "noul",
            "instructions": "Does the message convey urgency or time-sensitivity?",
            "criteria": {
                "true": "Explicitly time-sensitive or blocking",
                "false": "No urgency expressed"
            }
        }
    }
};

// Run the Actor and wait for it to finish
const run = await client.actor("sameh.jarour/jev-classifier").call(input);

// Fetch and print Actor results from the run's dataset (if any)
console.log('Results from dataset');
console.log(`💾 Check your data here: https://console.apify.com/storage/datasets/${run.defaultDatasetId}`);
const { items } = await client.dataset(run.defaultDatasetId).listItems();
items.forEach((item) => {
    console.dir(item);
});

// 📚 Want to learn more 📖? Go to → https://docs.apify.com/api/client/js/docs

```

## Python example

```python
from apify_client import ApifyClient

# Initialize the ApifyClient with your Apify API token
# Replace '<YOUR_API_TOKEN>' with your token.
client = ApifyClient("<YOUR_API_TOKEN>")

# Prepare the Actor input
run_input = {
    "items": [
        "Hi, I've been trying to connect my Stripe account for 3 days and the integration keeps failing. I'm losing sales. Please help ASAP.",
        {
            "subject": "Invoice question",
            "body": "Can you send me the invoice for August? No rush.",
        },
        "How much does the enterprise plan cost for 50 seats?",
    ],
    "questions": {
        "department": {
            "type": "choice",
            "instructions": "Which team should handle this message?",
            "criteria": {
                "billing": "Payments, invoicing, refunds, subscription charges",
                "technical": "Bugs, outages, integrations, errors",
                "sales": "Pricing, upgrades, new accounts, plan questions",
            },
        },
        "frustration": {
            "type": "score",
            "instructions": "How frustrated does the customer appear?",
            "criteria": [
                "Calm, just stating facts",
                "Frustrated but civil",
                "Very angry, strong language",
            ],
        },
        "is_urgent": {
            "type": "noul",
            "instructions": "Does the message convey urgency or time-sensitivity?",
            "criteria": {
                "true": "Explicitly time-sensitive or blocking",
                "false": "No urgency expressed",
            },
        },
    },
}

# Run the Actor and wait for it to finish
run = client.actor("sameh.jarour/jev-classifier").call(run_input=run_input)

# Fetch and print Actor results from the run's dataset (if there are any)
print(f"💾 Check your data here: https://console.apify.com/storage/datasets/{run.default_dataset_id}")
for item in client.dataset(run.default_dataset_id).iterate_items():
    print(item)

# 📚 Want to learn more 📖? Go to → https://docs.apify.com/api/client/python/docs/quick-start

```

## CLI example

```bash
echo '{
  "items": [
    "Hi, I'\''ve been trying to connect my Stripe account for 3 days and the integration keeps failing. I'\''m losing sales. Please help ASAP.",
    {
      "subject": "Invoice question",
      "body": "Can you send me the invoice for August? No rush."
    },
    "How much does the enterprise plan cost for 50 seats?"
  ],
  "questions": {
    "department": {
      "type": "choice",
      "instructions": "Which team should handle this message?",
      "criteria": {
        "billing": "Payments, invoicing, refunds, subscription charges",
        "technical": "Bugs, outages, integrations, errors",
        "sales": "Pricing, upgrades, new accounts, plan questions"
      }
    },
    "frustration": {
      "type": "score",
      "instructions": "How frustrated does the customer appear?",
      "criteria": [
        "Calm, just stating facts",
        "Frustrated but civil",
        "Very angry, strong language"
      ]
    },
    "is_urgent": {
      "type": "noul",
      "instructions": "Does the message convey urgency or time-sensitivity?",
      "criteria": {
        "true": "Explicitly time-sensitive or blocking",
        "false": "No urgency expressed"
      }
    }
  }
}' |
apify call sameh.jarour/jev-classifier --silent --output-dataset

```

## MCP server setup

```json
{
    "mcpServers": {
        "apify": {
            "type": "http",
            "url": "https://mcp.apify.com/?tools=fetch-actor-details,sameh.jarour/jev-classifier"
        }
    }
}
```

The hosted server signs you in with OAuth on first connect, so no API token belongs in this config. Clients without OAuth support can send an `Authorization: Bearer <APIFY_API_TOKEN>` header instead, using a token from API & Integrations in Apify Console (https://console.apify.com/settings/integrations).

## OpenAPI specification

Download the OpenAPI definition: https://api.apify.com/v2/actors/Gujd9n8KTgxTRbcUu/builds/pMBhkxoOvVcL5Agn8/openapi.json
