Developers

One call. A human goes.

Name a standard job and a place. The platform writes the instructions, finds a verified person nearby, proves they were there, and pays them. You get structured results and a webhook.

Thirty seconds

Request
curl -X POST https://tagteam-api.successagenticlabs.com/v1/tags/recipe \
  -H "Authorization: Bearer $IRL_TAGTEAM_API_KEY" \
  -H "Idempotency-Key: $(uuidgen)" \
  -H "Content-Type: application/json" \
  -d '{"recipe":"PROPERTY_OCCUPANCY_CHECK","location":{"lat":34.0522,"lng":-118.2437}}'
Response shape
{
  "tag_id": "<uuid>",
  "status": "open",
  "recipe": "PROPERTY_OCCUPANCY_CHECK",
  "recipe_version": "<integer>",
  "total_charge_cents": "<integer>",
  "partner_payout_cents": "<integer>",
  "results_url": "/v1/tags/<uuid>/result",
  "webhook_events": [
    "tag.claimed",
    "tag.submitted",
    "tag.verified",
    "tag.paid",
    "tag.failed"
  ]
}

This is the shape of the response, not a Tag that happened. Paste a key below to make the call for real.

This makes a real API call. With a live key it charges your card and opens a real Tag to real people. Your key is sent to the IRL TAGTEAM API and to nowhere else — it is never stored by this page.

Three ways in

TypeScript SDK

import { TagTeam } from '@irl/sdk';

const irl = new TagTeam(process.env.IRL_TAGTEAM_API_KEY!);

const tag = await irl.tags.fromRecipe({
  recipe: 'PROPERTY_OCCUPANCY_CHECK',
  location: { lat: 34.0522, lng: -118.2437 },
});

// Webhooks are better. This is the fallback.
const result = await irl.tags.waitForResult(tag.tag_id);
console.log(result.outcome, result.evidence.length);

MCP — for agents

{
  "mcpServers": {
    "irl-tagteam": {
      "command": "npx",
      "args": ["-y", "irl-tagteam-mcp"],
      "env": {
        "IRL_TAGTEAM_API_KEY": "irl_live_..."
      }
    }
  }
}

Sixteen tools, starting with list_recipes. The MCP server holds no rules of its own — every limit is enforced by the API, so an agent using these tools can do nothing a stolen key could not already do.

Webhooks

tag.claimed     a Partner is on the way
tag.submitted   evidence has arrived
tag.verified    the locks passed
tag.paid        the Partner has been paid
tag.failed      it did not happen, and why

Signed with HMAC-SHA256 and retried on a bounded schedule — one minute, five, thirty, then it stops and waits for you. Do not poll faster than once a minute; a person walking to a location does not move faster if you ask more often.

When one is not enough

Campaigns

await irl.campaigns.create({
  name: 'Q3 portfolio sweep',
  recipe: 'PROPERTY_EXTERIOR_INSPECTION',
  locations: properties.map(p => ({
    lat: p.lat, lng: p.lng, reference: p.id,
  })),
});

Two hundred locations is two hundred Tags — each with its own Partner, its own GPS-verified evidence and its own payment. That is the whole point: a partially completed campaign is still a precise record of which places were actually visited, not an average.

Schedules

await irl.schedules.create({
  name: 'Monday portfolio check',
  recipe: 'PROPERTY_SIGNAGE_CHECK',
  locations,
  schedule: { kind: 'weekly', weekdays: [1] },
  budget_cents: 200_000,
});

Only the next run is ever created. Nothing beyond it is charged or committed, and pausing stops all future runs immediately — Tags already created run to completion and are paid.

What we will not do

Every request is screened before anything is charged. A Tag that asks a person to enter private property, confront anybody, impersonate anybody, place anything in a mailbox, serve legal papers, handle hazardous materials, work at height or perform a regulated professional service is refused with 422 UNSAFE_TASK — with the matched phrase, so you can see why.

This is not a content filter bolted on afterwards. It is the reason a verified person is willing to take work from software they have never met.

Spending limits

Per Tag, per day, per month, per hour, per campaign, per schedule, and per Recipe if you want one. Every ceiling is checked inside the transaction that charges the card. The REST API, the SDK and the MCP server all pass through the same check — none of them can raise a limit.

GET /v1/limits

Coverage, before you commit

Ask whether we can actually serve a place. The answer is sometimes “no verified Partners in this area”, which costs us the sale and saves you an expired Tag.

GET /v1/coverage?lat=34.05&lng=-118.24

Errors worth branching on

CodeHTTPWhat to do
UNSAFE_TASK422Do not retry and do not reword. The work itself was refused.
SPENDING_LIMIT403A ceiling was reached. The response names which one and its value.
QUOTA_EXCEEDED402Monthly plan quota. Upgrade or wait for the reset.
IDEMPOTENCY_CONFLICT409That key was used for a different body. A key is a promise about one request.
VALIDATION_FAILED400Details name the field. An unknown Recipe lists the ones that exist.
KILL_SWITCH503Operations disabled this category. Retry later; nothing was charged.
RATE_LIMITED429Back off. Retrying the same key is safe.