---
title: "Propose one or two ways to search"
method: POST
path: "/api/v1/agent/intake/directions"
tags: ["Agent"]
---

# Propose one or two ways to search

`POST /api/v1/agent/intake/directions`

## Request

- Base URL: `https://api.flexiple.com` (the document declares no server; this is the origin it was published from)
- URL: `https://api.flexiple.com/api/v1/agent/intake/directions`
- Auth: HTTP bearer

1 or 2 directions, exactly one recommended, each with its exact filters and rubric. Rails counts each tree: 0 or over 5,000 is refused, and so is a rubric that breaks its rules. The reply's `phase` is "directions" (end your turn) or "saving" (Rails saved the recommended one; end your turn).

## Request body

- object
  - `research` object
    - `summary` string: 3 to 5 bullet points, one per line, each starting with "- ". Each bullet is one short, plain sentence for a non-technical recruiter. No jargon, no semicolons, no hedging. Together they cover who to look for, where they work now (name the peer companies when known), how pay compares with the budget, and the one thing to check when reviewing people. For example: - Look for backend engineers who build payment systems. - Most work at fintechs like Razorpay, PhonePe and Juspay. - Your budget covers about 7 in 10 of them. - When you review people, check they have run their own code in production.
    - `sections` object[]
      - `key` 'job' | 'titles' | 'skills' | 'seniority' | 'talent_pool' | 'great_vs_average' | 'company_fit' | 'backgrounds' | 'how_to_find', required
      - `peek` string, required
      - `bullets` string[], required
      - `sources` object[], required
        - `label` string, required
        - `url` string, nullable
    - `funnel` object[]
      - `label` string, required
      - `count` integer, required
  - `directions` object[], required
    - `id` string
    - `name` string, required: 2-4 plain words saying what makes this direction different
    - `tradeoff` string, required: One short line: what the recruiter gets with this direction
    - `recommended` boolean, required
    - `summary` string, required
    - `reasoning` string, required
    - `filters` object, required: A filter tree. A leaf is {"field": F, "operator": O, "value": V}. Groups are {"and": [...]} or {"or": [...]} and may nest; a single leaf on its own is also valid. Every criterion is a requirement — there is no "nice to have", so put anything optional in an "or" or leave it out. Example: {"and": [{"field": "skills", "operator": "any_of", "value": [12, 44]}, {"field": "months_of_experience", "operator": "gte", "value": 5}]} Fields, grouped by the operators they accept: any_of, all_of, none_of, exists spoken_languages (Spoken Languages), employment_types (Employment Types), profession (Profession), designations (Designations), relocation_places (Relocation Places), all_locations (All Locations), skills (Skills), experience_in_skill (Experience in Skill), companies (Company), company_types (Company Type), company_business_models (Business Type), company_industries (Industry), company_funding_stages (Funding Stage), company_sizes (Company Sizes), education_degrees (Education Degree), education_fields (Education Field), colleges (Colleges) eq, neq, gt, gte, lt, lte, between, exists current_ctc (Current CTC, in LPA), expected_ctc (Expected CTC, in LPA), resume_completeness (Resume Completeness), months_of_experience (Experience, in years), experience_in_current_position (Experience in Current Position, in years), experience_in_current_company (Experience in Current Company, in years), average_experience (Average Experience per Company, in years), maximum_experience (Maximum Experience in a Company, in years), year_of_graduation (Year of Graduation) eq, neq, in, not_in, exists gender (Gender), notice_period (Notice Period) eq is_active (Active), looking_for_job (Open to work) matches keywords (Keywords) any_of, none_of, exists current_location (Current Location) Most fields take their value directly. These take an object instead, one key per input: spoken_languages: {"value": [id, ...], "min_proficiency": 0 (Elementary)|1 (Limited Working)|2 (Professional Working)|3 (Full Professional)|4 (Native Or Bilingual)} current_ctc, expected_ctc: {"value": number, "currency": "INR"|"USD"} designations, companies: {"value": [id, ...], "scope": "current_or_past"|"current"|"past"} experience_in_skill: {"value": [id, ...], "scope": ["0_1"|"1_3"|"3_5"|"5_7"|"7_plus", ...]} With "between", "min" and "max" replace "value" — {"min": 5, "max": 8}, and inside the object above where the field has one: {"min": 25, "max": 40, "currency": "INR"}. Some id fields also take groups — one id standing for a set the recruiter's dropdowns offer as a single row: a metro area for locations, an institution family for colleges, a discipline for skills and designations, a kind of employer for companies (IT services and outsourcing firms, fintechs). The lookup returns them in their own "groups" list, apart from the plain rows. Put a group's id under "groups" in the field's value object — {"value": [ids...], "groups": [group ids...]} where the field takes a plain list, an extra key where it already takes an object; "value" may be empty — and never list its members yourself. Prefer a group whenever the brief means the whole of what it names: a city and its suburbs, an IIT-type family, every title in a discipline. Fields that take groups: designations, current_location, relocation_places, all_locations, skills, companies, colleges. Fields with a fixed set of values. Send the value, never the label in brackets: gender: "male"|"female" notice_period: "immediately_available"|"1_to_15_days"|"16_to_30_days"|"31_to_45_days"|"46_to_60_days"|"61_to_90_days"|"more_than_90_days" employment_types: "Full-time"|"Part-time"|"Self-employed"|"Freelance"|"Internship"|"Trainee"|"Apprenticeship"|"Contract"|"Temporary Staff"|"Contract Full-time"|"Contract Part-time"|"Permanent Full-time"|"Permanent Part-time"|"Seasonal"|"Casual / On-call"|"Co-op"|"Permanent"|"Indirect Contract"|"On-Call" company_sizes: "self_employed"|"2-10"|"11-50"|"51-200"|"201-500"|"501-1000"|"1001-5000"|"5001-10,000"|"10,000+" Values for fields that hold ids come from the lookup endpoint for this resource (names in, ranked ids out). It resolves: skills, designations, colleges, education_degrees, education_fields, current_location, companies, profession, company_types, company_business_models, company_industries, company_funding_stages. Never invent an id, and never pass a name where an id is wanted. An id field the lookup does not resolve cannot be filled through this API — leave it out.
    - `filter_summary` object[], required
      - `label` string, required
      - `value` string, required
    - `rubric` object, required
      - `metrics` object[], required: The whole rubric, every metric with its levels — not a diff. The save also checks what this schema cannot: scored weights total exactly 100, one level per score, unique metric names, and at least one scored (non-mandatory) metric
        - `name` string, required
        - `scale_max` 1 | 2, required: 1 for a yes/no metric, 2 for a three-level metric (scored 0-2). Levels describe scores 1..scale_max only
        - `weight` integer: Integer percentage, 1-100. Scored (non-mandatory) metrics must total exactly 100. Omit the key entirely on a mandatory metric
        - `mandatory` boolean: Must-have gate: scale_max 1, exactly one level (score 1), and no weight key. A candidate who fails it scores 0 overall
        - `levels` object[], required: Exactly one entry per score 1..scale_max, each with a non-empty description. Never include a score 0 entry
          - `score` integer, required: 1..scale_max. Score 0 is implicit ("otherwise 0") and is never sent as a level
          - `description` string, required

## Response `200`

Priced and recorded, with the phase the run moved to; or refused

- object
  - `data` object, required
    - `phase` 'directions' | 'saving'
    - `reply` string: What to do next
    - `directions` object[]
      - `id` string, required
      - `name` string, required
      - `tradeoff` string, required
      - `recommended` boolean, required
      - `count` integer, required
    - `refused` boolean: Present and true only when a rule was broken
    - `reason` string: Why it was refused, in a plain sentence

---

[API](https://skmtc.dev/flexiple/apis/flexiple-platform-api-v1.md) - [All operations](https://skmtc.dev/flexiple/apis/flexiple-platform-api-v1/llms.txt) - [OpenAPI document](https://skmtc.dev/flexiple/apis/flexiple-platform-api-v1/revisions/27e7987859f2?raw)
