Customer API

Use cases

What teams build on the Agent API, with the calls behind each, and how to connect Copilot Studio

What recruitment teams build on the Agent API, each with the calls it takes. Every example uses $WINTRO_TOKEN and https://www.wintro.app.

A sourcing agent that searches warm before cold

A recruiter asks their agent for candidates for a vacancy. The agent tries the people the company already knows first (its ATS, then Wintro’s network of colleagues) and goes to LinkedIn search only for what is left.

Recruiter: "Find me D365 F&O consultants for VAC-2291."

1. vacancies/list       {"atsId": "VAC-2291"}                    → vacancyId 4182 (live: true)
2. candidates/ranked    {"vacancyId": 4182, "limit": 10}         → likeliest hires, each with introducers
3. answer               name, current job, "Pieter De Smet knows her", wintroUrl
4. only if too few      search LinkedIn, then candidates/lookup {"linkedins": [...]} for everyone found there, in one call

The vacancy id from your ATS (Carerix, say) is enough: atsId finds it in Wintro. If live is false, Wintro has no candidates for it yet: stay with your ATS and LinkedIn. Ranked candidates need no lookup: blocked and closed ones are left out, and each row says what already happened.

Check before anyone reaches out

Your ATS does not see LinkedIn messages sent or a colleague’s referral in progress. Before an agent or recruiter contacts people found outside Wintro (your ATS, a LinkedIn search), look them up, up to 25 in one call:

curl -s https://www.wintro.app/api/wintro/app/candidates/lookup \
  -H "Authorization: Bearer $WINTRO_TOKEN" \
  -H "Content-Type: application/json" \
  -d '{"linkedins": ["https://www.linkedin.com/in/lotte-janssens", "jan-peeters", "els-maes"]}'
{
  "people": [
    {
      "linkedin": "https://www.linkedin.com/in/lotte-janssens",
      "found": true,
      "profile": { "profileId": 55120, "name": "Lotte Janssens" },
      "introducers": [{ "name": "Pieter De Smet", "profileUrl": "https://www.linkedin.com/in/pieter-de-smet" }],
      "matches": [{ "matchId": 918273, "vacancyId": 4182, "vacancyTitle": "Dynamics 365 F&O Consultant", "vacancyOpen": true, "score": 84, "status": "referred by Pieter De Smet: interview", "wintroUrl": "https://www.wintro.app/dashboard/candidates/4182/live?search=55120" }]
    },
    { "linkedin": "jan-peeters", "found": true, "blocked": true, "profile": { "profileId": 61002, "name": "Jan Peeters" } },
    { "linkedin": "els-maes", "found": false }
  ]
}
  • blocked: true: your recruiters blocked or snoozed them. Stop.
  • A match whose status starts with referred, recommended or a stage word without a date (interview, contacted, hired): a colleague’s referral is running. Don’t approach them separately.
  • contacted 5 Oct, with a date: a recruiter already reached out.
  • rejected 6 Oct or not a fit, says An Claes 2 Oct: your team already decided against them for that vacancy.
  • introducers: ask one of them for a warm introduction instead of a cold message.
  • found: false: nobody here knows them. A cold approach is yours to decide.

Each person counts as one call against your limits.

Let your ambassadors do the introducing

Instead of messaging the candidate, the agent tells the recruiter which colleague to ask for an introduction, and whether they were asked already:

curl -s https://www.wintro.app/api/wintro/app/candidates/introducers \
  -H "Authorization: Bearer $WINTRO_TOKEN" \
  -H "Content-Type: application/json" \
  -d '{"matchId": 918273}'

nudgedAt: null: nobody asked this colleague yet. The recruiter opens the candidate’s wintroUrl and asks from Wintro, so the referral and its reward are tracked.

Who does this team know?

Start from people instead of a vacancy: the candidates a team, a manager or a new hire knows for one vacancy.

curl -s https://www.wintro.app/api/wintro/app/candidates/ranked \
  -H "Authorization: Bearer $WINTRO_TOKEN" \
  -H "Content-Type: application/json" \
  -d '{
    "vacancyId": 4182,
    "colleagues": [
      "https://www.linkedin.com/in/pieter-de-smet",
      "https://www.linkedin.com/in/an-claes"
    ]
  }'

Colleagues who don’t share their network come back in unknownColleagues.

A morning digest

A script for each open vacancy: the strong candidates nobody has acted on (no status), posted to your team’s channel.

import os, requests

API = "https://www.wintro.app/api/wintro/app/"
H = {"Authorization": f"Bearer {os.environ['WINTRO_TOKEN']}"}
call = lambda action, body: requests.post(API + action, json=body, headers=H).json()

for v in call("vacancies/list", {"live": True})["vacancies"]:
    fresh = [c for c in call("candidates/ranked", {"vacancyId": v["vacancyId"], "minScore": 80})["candidates"]
             if "status" not in c]
    for c in fresh[:3]:
        who = ", ".join(i["name"] for i in c.get("introducers", [])) or "nobody yet"
        print(f'{v["title"]}: {c["name"]} ({c.get("currentTitle", "?")}), known by {who}: {c["wintroUrl"]}')

Copilot Studio

  1. Download the connector file

    A recruiter admin, in Wintro, Settings > API: download wintro-connector.swagger.json under Agent API (it shows only when your plan includes it). Create a token there too, with Agent API ticked.

  2. Make a custom connector

    In Power Apps, Custom connectors > New custom connector > Import an OpenAPI file, and pick that file. Security is already set: an API key in the Authorization header.

  3. Connect

    Create a connection and paste Bearer followed by your token, with the space:

    Bearer wintro_...
  4. Add the actions to your agent

    In Copilot Studio, add the connector’s actions under Tools. Each action carries a description written for the agent, so it knows when to use it.

Then give your agent its instructions. A start to paste and adapt:

You help our recruiters find candidates through people we already know.
- Start a run with agent/status. If an action is paused, say so and use the others.
  On a 429 or 503, wait the Retry-After seconds before trying again.
- For a vacancy from our ATS, find it with vacancies/list {"atsId": "..."}.
  If it is not live, Wintro has no candidates for it: say so and search elsewhere.
- Get candidates with candidates/ranked, best first. Always name who can introduce
  each one, and link the wintroUrl.
- Candidates from candidates/ranked are already checked. Anyone found elsewhere
  (our ATS, a LinkedIn search): run candidates/lookup on their LinkedIn URLs first,
  all of them in one call with linkedins.
  Never suggest contacting someone blocked, with a referral running, or already
  contacted (a status with "contacted" and a date).
- Prefer a warm introduction by a colleague over a cold message.