# Patch Email Send

`PATCH /v1/email/batches/{batch_id}/sends/{send_id}`

Re-steer one send: its pace, its hours, its daily cap, its start time.

Never its sender or its scope — to change what it covers, cancel it and
create another. `start_at` moves only before the send has begun.

Authenticate with `Authorization: Bearer $TALQING_API_KEY`. Errors use the shared envelope: https://docs.talqing.com/api-reference/errors.md

## OpenAPI

```json
{
 "openapi":"3.1.0",
 "servers":[
  {
   "description":"Talqing API",
   "url":"https://api.talqing.com"
  }
 ],
 "paths":{
  "/v1/email/batches/{batch_id}/sends/{send_id}":{
   "patch":{
    "description":"Re-steer one send: its pace, its hours, its daily cap, its start time.\n\nNever its sender or its scope \u2014 to change what it covers, cancel it and\ncreate another. `start_at` moves only before the send has begun.",
    "operationId":"email.batches.sends.update",
    "parameters":[
     {
      "in":"path",
      "name":"batch_id",
      "required":true,
      "schema":{
       "format":"uuid",
       "title":"Batch Id",
       "type":"string"
      }
     },
     {
      "in":"path",
      "name":"send_id",
      "required":true,
      "schema":{
       "format":"uuid",
       "title":"Send Id",
       "type":"string"
      }
     }
    ],
    "requestBody":{
     "content":{
      "application/json":{
       "schema":{
        "$ref":"#/components/schemas/PatchEmailSendRequest"
       }
      }
     },
     "required":true
    },
    "responses":{
     "200":{
      "content":{
       "application/json":{
        "schema":{
         "$ref":"#/components/schemas/EmailSendResponse"
        }
       }
      },
      "description":"Successful Response"
     },
     "400":{
      "$ref":"#/components/responses/BadRequest"
     },
     "401":{
      "$ref":"#/components/responses/Unauthorized"
     },
     "403":{
      "$ref":"#/components/responses/Forbidden"
     },
     "404":{
      "$ref":"#/components/responses/NotFound"
     },
     "409":{
      "$ref":"#/components/responses/Conflict"
     },
     "422":{
      "$ref":"#/components/responses/ValidationFailed"
     },
     "default":{
      "$ref":"#/components/responses/Error"
     }
    },
    "security":[
     {
      "BearerAuth":[]
     },
     {
      "SessionCookie":[]
     }
    ],
    "summary":"Patch Email Send",
    "tags":[
     "email"
    ]
   }
  }
 },
 "components":{
  "responses":{
   "BadRequest":{
    "content":{
     "application/json":{
      "schema":{
       "$ref":"#/components/schemas/ErrorResponse"
      }
     }
    },
    "description":"Well-formed, but rejected by a rule; `detail.errors` lists each problem."
   },
   "Conflict":{
    "content":{
     "application/json":{
      "schema":{
       "$ref":"#/components/schemas/ErrorResponse"
      }
     }
    },
    "description":"The resource's current state forbids this \u2014 a name already taken, a job already running."
   },
   "Error":{
    "content":{
     "application/json":{
      "schema":{
       "$ref":"#/components/schemas/ErrorResponse"
      }
     }
    },
    "description":"Unexpected error. Every error this API returns carries this body."
   },
   "Forbidden":{
    "content":{
     "application/json":{
      "schema":{
       "$ref":"#/components/schemas/ErrorResponse"
      }
     }
    },
    "description":"Authenticated, but this organization role may not perform the operation."
   },
   "NotFound":{
    "content":{
     "application/json":{
      "schema":{
       "$ref":"#/components/schemas/ErrorResponse"
      }
     }
    },
    "description":"No such resource in this organization."
   },
   "Unauthorized":{
    "content":{
     "application/json":{
      "schema":{
       "$ref":"#/components/schemas/ErrorResponse"
      }
     }
    },
    "description":"Missing credential, or one that is revoked or no longer a member of this organization."
   },
   "ValidationFailed":{
    "content":{
     "application/json":{
      "schema":{
       "$ref":"#/components/schemas/ErrorResponse"
      }
     }
    },
    "description":"The request did not match this operation's schema; `detail.errors` lists each field."
   }
  },
  "schemas":{
   "EmailSendCounts":{
    "description":"Where this send's rows are.\n\n``total`` is the rows a `selected` send was created with, and null for an\n`all` send, which cannot know it while drafting runs. ``queued`` and\n``drafting`` are what it still covers \u2014 drafts ready to go, and rows still\nbeing written \u2014 so both are 0 once it has ended.",
    "properties":{
     "drafting":{
      "title":"Drafting",
      "type":"integer"
     },
     "queued":{
      "title":"Queued",
      "type":"integer"
     },
     "send_failed":{
      "title":"Send Failed",
      "type":"integer"
     },
     "sending":{
      "title":"Sending",
      "type":"integer"
     },
     "sent":{
      "title":"Sent",
      "type":"integer"
     },
     "skipped":{
      "title":"Skipped",
      "type":"integer"
     },
     "total":{
      "anyOf":[
       {
        "type":"integer"
       },
       {
        "type":"null"
       }
      ],
      "title":"Total"
     }
    },
    "required":[
     "total",
     "queued",
     "drafting",
     "sending",
     "sent",
     "send_failed",
     "skipped"
    ],
    "title":"EmailSendCounts",
    "type":"object"
   },
   "EmailSendResponse":{
    "properties":{
     "batch_id":{
      "format":"uuid",
      "title":"Batch Id",
      "type":"string"
     },
     "counts":{
      "$ref":"#/components/schemas/EmailSendCounts"
     },
     "created_at":{
      "format":"date-time",
      "title":"Created At",
      "type":"string"
     },
     "failure_reason":{
      "anyOf":[
       {
        "type":"string"
       },
       {
        "type":"null"
       }
      ],
      "title":"Failure Reason"
     },
     "finished_at":{
      "anyOf":[
       {
        "format":"date-time",
        "type":"string"
       },
       {
        "type":"null"
       }
      ],
      "title":"Finished At"
     },
     "from_email":{
      "title":"From Email",
      "type":"string"
     },
     "from_name":{
      "anyOf":[
       {
        "type":"string"
       },
       {
        "type":"null"
       }
      ],
      "title":"From Name"
     },
     "id":{
      "format":"uuid",
      "title":"Id",
      "type":"string"
     },
     "next_send_at":{
      "anyOf":[
       {
        "format":"date-time",
        "type":"string"
       },
       {
        "type":"null"
       }
      ],
      "title":"Next Send At"
     },
     "next_send_reason":{
      "anyOf":[
       {
        "enum":[
         "start",
         "window",
         "daily_cap",
         "retry",
         "gap",
         "drafting"
        ],
        "type":"string"
       },
       {
        "type":"null"
       }
      ],
      "title":"Next Send Reason"
     },
     "reply_to":{
      "anyOf":[
       {
        "type":"string"
       },
       {
        "type":"null"
       }
      ],
      "title":"Reply To"
     },
     "scope":{
      "enum":[
       "all",
       "selected"
      ],
      "title":"Scope",
      "type":"string"
     },
     "send_attempts":{
      "title":"Send Attempts",
      "type":"integer"
     },
     "send_daily_cap":{
      "anyOf":[
       {
        "discriminator":{
         "mapping":{
          "fixed":"#/components/schemas/FixedDailyCap",
          "ramp":"#/components/schemas/RampDailyCap"
         },
         "propertyName":"kind"
        },
        "oneOf":[
         {
          "$ref":"#/components/schemas/FixedDailyCap"
         },
         {
          "$ref":"#/components/schemas/RampDailyCap"
         }
        ]
       },
       {
        "type":"null"
       }
      ],
      "title":"Send Daily Cap"
     },
     "send_daily_cap_today":{
      "anyOf":[
       {
        "type":"integer"
       },
       {
        "type":"null"
       }
      ],
      "title":"Send Daily Cap Today"
     },
     "send_gap_seconds":{
      "title":"Send Gap Seconds",
      "type":"integer"
     },
     "send_retry_after_minutes":{
      "title":"Send Retry After Minutes",
      "type":"integer"
     },
     "start_at":{
      "anyOf":[
       {
        "format":"date-time",
        "type":"string"
       },
       {
        "type":"null"
       }
      ],
      "title":"Start At"
     },
     "started_at":{
      "anyOf":[
       {
        "format":"date-time",
        "type":"string"
       },
       {
        "type":"null"
       }
      ],
      "title":"Started At"
     },
     "status":{
      "enum":[
       "scheduled",
       "sending",
       "paused",
       "sent",
       "canceled",
       "failed"
      ],
      "title":"Status",
      "type":"string"
     },
     "timezone":{
      "title":"Timezone",
      "type":"string"
     },
     "window":{
      "anyOf":[
       {
        "$ref":"#/components/schemas/TimeWindow"
       },
       {
        "type":"null"
       }
      ]
     }
    },
    "required":[
     "id",
     "batch_id",
     "scope",
     "status",
     "failure_reason",
     "from_email",
     "from_name",
     "reply_to",
     "start_at",
     "timezone",
     "window",
     "send_attempts",
     "send_retry_after_minutes",
     "send_gap_seconds",
     "send_daily_cap",
     "send_daily_cap_today",
     "counts",
     "next_send_at",
     "next_send_reason",
     "created_at",
     "started_at",
     "finished_at"
    ],
    "title":"EmailSendResponse",
    "type":"object"
   },
   "ErrorBody":{
    "description":"The structured half of our error contract: a human `message` plus a list\nof individual `errors` (used wherever we surface many problems at once,\nincluding tool publish, op-tree checks, and request validation). The global\nexception handlers normalize every API error to\n`{detail: {message, errors, code}}`, so SDKs can parse one shape consistently.",
    "properties":{
     "code":{
      "anyOf":[
       {
        "type":"string"
       },
       {
        "type":"null"
       }
      ],
      "default":null,
      "description":"A stable identifier for this error, when it has one.",
      "title":"Code"
     },
     "errors":{
      "items":{
       "type":"string"
      },
      "title":"Errors",
      "type":"array"
     },
     "message":{
      "title":"Message",
      "type":"string"
     }
    },
    "required":[
     "message",
     "errors"
    ],
    "title":"ErrorBody",
    "type":"object"
   },
   "ErrorResponse":{
    "description":"The body of every error response, at every status code.",
    "properties":{
     "detail":{
      "$ref":"#/components/schemas/ErrorBody"
     }
    },
    "required":[
     "detail"
    ],
    "title":"ErrorResponse",
    "type":"object"
   },
   "FixedDailyCap":{
    "additionalProperties":false,
    "description":"The same limit every day.",
    "properties":{
     "kind":{
      "const":"fixed",
      "title":"Kind",
      "type":"string"
     },
     "limit":{
      "minimum":1.0,
      "title":"Limit",
      "type":"integer"
     }
    },
    "required":[
     "kind",
     "limit"
    ],
    "title":"FixedDailyCap",
    "type":"object"
   },
   "PatchEmailSendRequest":{
    "additionalProperties":false,
    "description":"Re-steer one send: its pacing, its hours, its ceiling, its start time.\n\nNever its sender and never its scope \u2014 \"re-steer the pacing, never the\ncontents\". Widening a send is another send; narrowing one has no defensible\nanswer to \"which rows does it keep?\". To change what a send covers, cancel it\n\u2014 its unsent rows simply stay drafts \u2014 and create another.",
    "properties":{
     "send_attempts":{
      "ge":1,
      "le":5,
      "title":"Send Attempts",
      "type":"integer"
     },
     "send_daily_cap":{
      "anyOf":[
       {
        "discriminator":{
         "mapping":{
          "fixed":"#/components/schemas/FixedDailyCap",
          "ramp":"#/components/schemas/RampDailyCap"
         },
         "propertyName":"kind"
        },
        "oneOf":[
         {
          "$ref":"#/components/schemas/FixedDailyCap"
         },
         {
          "$ref":"#/components/schemas/RampDailyCap"
         }
        ]
       },
       {
        "type":"null"
       }
      ],
      "title":"Send Daily Cap"
     },
     "send_gap_seconds":{
      "ge":1,
      "le":3600,
      "title":"Send Gap Seconds",
      "type":"integer"
     },
     "send_retry_after_minutes":{
      "ge":5,
      "le":1440,
      "title":"Send Retry After Minutes",
      "type":"integer"
     },
     "start_at":{
      "anyOf":[
       {
        "format":"date-time",
        "type":"string"
       },
       {
        "type":"null"
       }
      ],
      "title":"Start At"
     },
     "timezone":{
      "title":"Timezone",
      "type":"string"
     },
     "window":{
      "anyOf":[
       {
        "$ref":"#/components/schemas/TimeWindow"
       },
       {
        "type":"null"
       }
      ]
     }
    },
    "title":"PatchEmailSendRequest",
    "type":"object"
   },
   "RampDailyCap":{
    "additionalProperties":false,
    "description":"`start` a day, raised by `step` every `interval_days` sending days, up to `end`.",
    "properties":{
     "end":{
      "title":"End",
      "type":"integer"
     },
     "interval_days":{
      "maximum":30.0,
      "minimum":1.0,
      "title":"Interval Days",
      "type":"integer"
     },
     "kind":{
      "const":"ramp",
      "title":"Kind",
      "type":"string"
     },
     "start":{
      "minimum":1.0,
      "title":"Start",
      "type":"integer"
     },
     "step":{
      "minimum":1.0,
      "title":"Step",
      "type":"integer"
     }
    },
    "required":[
     "kind",
     "start",
     "end",
     "step",
     "interval_days"
    ],
    "title":"RampDailyCap",
    "type":"object"
   },
   "TimeWindow":{
    "description":"The hours a list may run in, on the list's own clock.\n\nShared rather than duplicated, for the same reason ``window_state`` is: a\ncall batch and an email send run store the same three values under the same\nnames and must not each get their own copy of the rules. The field that\ncarries one is named for what it gates \u2014 ``calling_window`` on a campaign,\n``window`` on an email batch and its runs.\n\nA window that crosses midnight (``21:00``-``06:00``) is valid and means\nexactly what an evening consumer-calling window means: the day check applies\nto the *start* side, so ``21:00``-``06:00`` on ``days: [5]`` runs Friday\n21:00 through Saturday 06:00.",
    "properties":{
     "days":{
      "default":[
       1,
       2,
       3,
       4,
       5,
       6,
       7
      ],
      "description":"ISO weekdays the window opens on, 1 = Monday.",
      "items":{
       "type":"integer"
      },
      "title":"Days",
      "type":"array"
     },
     "end":{
      "format":"time",
      "title":"End",
      "type":"string"
     },
     "start":{
      "format":"time",
      "title":"Start",
      "type":"string"
     }
    },
    "required":[
     "start",
     "end"
    ],
    "title":"TimeWindow",
    "type":"object"
   }
  }
 }
}
```
