Skip to content
View as Markdown

Move a lead's card ​

PUT /v1/leads/{lead_id}/stage

Moves the lead's pipeline card to another stage of its pipeline, the way a move on the board does.

Scope: pipeline:write

The card is the one GET /v1/leads/{lead_id} returns as card: for a member who may open only a follow-through card of the lead, that card, never the main card. stage, expected_stage, previous_stage, error.current_stage and error.valid_stages all refer to it. The move is recorded in the card's stage history and the pipeline's stage automations run exactly as when your team moves the card. A card already in stage answers 200 with changed: false whatever expected_stage says, so retrying after a timeout is safe.

Compare and set: send expected_stage with every automated move. The check and the move are one atomic write, so if someone moved the card since you read it, nothing changes and you get 409 stage_conflict with the card's current_stage. Read the lead again and decide again; do not resend the same move blindly.

Human placement wins. A move not made for an active team member (no acting_member_id, or one that is not an active member) never overrides a person: if the card was last placed by a team member, stage is one only a person may place cards in (the AI follow-up stage, ai-follow-up), or the card is a follow-through card (only a person moves those), the request fails with 409 member_required and nothing changes.

The lead must belong to a campaign the key may reach and be one the key's member can see in DialEcho, otherwise 404.

Path parameters ​

NameTypeRequiredDescription
lead_idUUIDYesThe lead, as POST /v1/leads returned it.

Body ​

Content type: application/json

NameTypeRequiredDescription
stagestringYesSlug of the stage to move the card to, as card.stage and the pipeline board show slugs. It must be a stage of the card's pipeline. 1 to 200 characters after trimming.
expected_stagestringNoSlug of the stage you believe the card is in now. If it is in any other stage nothing changes and the request fails with 409 stage_conflict. Must not be blank. 1 to 200 characters after trimming.
acting_member_idUUIDNoThe team member you are moving the card for, for example the member.id a verified lead-action token returned. If it is an active member of your organization the move is recorded as theirs, made through the API, exactly as if they had moved the card on the board; otherwise it is recorded as a move by the API.

Response ​

Status: 200 OK

NameTypeDescription
lead_idUUIDThe lead.
pipeline_lead_idUUIDThe card that was moved.
stagestringThe card's stage now (the stage you sent).
previous_stagestringThe stage the card was moved from; equals stage when nothing changed.
changedbooleanfalse when the card was already in stage: nothing was recorded and no automation ran.

Example request ​

curl

bash
curl -X PUT "https://development.agencydevworks.ai/v1/leads/aaaaaaaa-0000-4000-8000-000000000001/stage" \
  -H "Authorization: Bearer dei_your_key" \
  -H "Content-Type: application/json" \
  -d '{
  "stage": "won",
  "expected_stage": "appointment",
  "acting_member_id": "ffffffff-0000-4000-8000-000000000001"
}'

JavaScript

js
const response = await fetch("https://development.agencydevworks.ai/v1/leads/aaaaaaaa-0000-4000-8000-000000000001/stage", {
  method: "PUT",
  headers: {
    "Authorization": "Bearer dei_your_key",
    "Content-Type": "application/json",
  },
  body: JSON.stringify({
    "stage": "won",
    "expected_stage": "appointment",
    "acting_member_id": "ffffffff-0000-4000-8000-000000000001"
  }),
});
const data = await response.json();

Example response ​

Status: 200 OK

json
{
  "lead_id": "aaaaaaaa-0000-4000-8000-000000000001",
  "pipeline_lead_id": "dddddddd-0000-4000-8000-000000000001",
  "stage": "won",
  "previous_stage": "appointment",
  "changed": true
}

Errors ​

HTTPCodeWhen
403insufficient_scopeThe key does not have pipeline:write. Checked before the body is validated.
404not_foundThe lead does not exist or the key cannot reach it.
409no_pipeline_cardThe lead has no pipeline card. Nothing was moved.
409stage_conflictThe card is not in expected_stage (or moved while the request ran). error.current_stage is its stage now. Nothing was moved.
409member_requiredA move not made for an active team member was refused because a person placed the card, only a person may place cards in stage, or the card is a follow-through card. error.current_stage is its stage. Nothing was moved.
413payload_too_largeThe body is larger than 1 MB. It was not read and nothing was written.
422unknown_stagestage is not a stage of the card's pipeline. error.valid_stages lists that pipeline's slugs in board order.
422invalid_requestlead_id is not a UUID, or the body is invalid: stage missing or blank, a blank expected_stage, an acting_member_id that is not a UUID, or an unknown field.

Every endpoint can also answer 401 invalid_api_key, 429 rate_limited and 503 dependency_unavailable. See Errors in the overview.