> ## Documentation Index
> Fetch the complete documentation index at: https://docs.isnap.ai/llms.txt
> Use this file to discover all available pages before exploring further.

# Update the configuration of a line

> Sets per-line overrides of the send configuration of a line.

* **Credential:** an API key of the owner of the line. See [Configuration](/guides/managing-lines#configuration) for the direction rule, the ranges and the way back to a default.
* **Line-scoped keys:** a [line-scoped key](/authentication#line-scoped-keys) gets `403 forbidden` unless the line is in its list.
* **`Idempotency-Key`:** not honored. The operation sets the keys you send and keeps the others, so the same request sent twice leaves the line in the same state.
* **Events:** none. See [What events do not announce](/webhooks/event-catalog#what-events-do-not-announce).
* **Body:** `null` is not accepted for any key, and an unknown key is refused. To remove an override, send the key with its default value. For `activity_curve`, send the `default_activity_curve` of [`GET /v1/lines/{id}/config`](/api-reference/lines/get-line-config): a curve that gives every hour the same weight as that curve, an hour with no entry counting as 0, removes the override. A request that does not send `activity_curve` leaves its override in place.

## Errors

| Status | `error.code` | When |
| - | - | - |
| 400 | `validation_failed` | The body has an unknown key or a `null` value, a number is outside the range that the schema of this operation accepts, `timezone` is not a valid IANA time zone name, or an `activity_curve` entry has an `hour` outside 0 to 23 or a `weight` that is negative or not an integer. |
| 403 | `forbidden` | The request uses a line-scoped key, and the line is not in its list. |
| 403 | `cannot_increase_limit` | A limit is inside its accepted range and above its default. On a BYOD line, this applies only to `max_queue_depth` and to the three reply limits. |
| 403 | `cannot_decrease_delay` | `min_inter_message_seconds` or `min_inter_new_contact_seconds` is below its default. |
| 404 | `not_found` | No line has this id, or you do not own the line. |
| 422 | `limit_out_of_bounds` | One of the five message limits is outside its accepted range. For one key, this check comes before `cannot_increase_limit`: on every line, a value above the range returns this code or `400 validation_failed`, never `cannot_increase_limit`. `error.issues[0]` carries the allowed `min` and `max`. |
| 422 | `invalid_activity_curve` | `activity_curve` is empty, names an hour twice, or has a total weight of 0. |

The errors that every operation shares are in [Errors](/errors-and-rate-limits#errors).


## OpenAPI

````yaml PATCH /v1/lines/{id}/config
openapi: 3.0.0
info:
  title: iSnap API
  version: 2.45.0
  description: >-
    The iSnap API sends and receives iMessage, RCS and SMS on real phone lines,
    manages those lines, and reports events through webhooks. Every message is
    sent to a real recipient, with an `isnap_live_` key and with an
    `isnap_test_` key alike. Retry a `429` after `Retry-After` seconds. Retry a
    `500` or a `503` up to 2 times, with exponential backoff. Do not retry any
    other `4xx`: fix the request. Retry a write only on an operation that honors
    `Idempotency-Key`, with the key of the first attempt. Responses carry
    personal data: handles, names and message text.
servers:
  - url: https://api.isnap.ai
security:
  - bearerAuth: []
paths:
  /v1/lines/{id}/config:
    patch:
      summary: Update the configuration of a line
      description: >-
        Sets overrides of the sending configuration on a line you own, and
        returns the resulting configuration. Accepts an API key. Send only the
        keys to change. To remove an override, send the key with its default
        value: `null` is not accepted. For `activity_curve`, the default value
        is `default_activity_curve`.


        A limit can only be lowered below its default, and the two delays,
        `min_inter_message_seconds` and `min_inter_new_contact_seconds`, can
        only be raised above theirs. On a BYOD line, the five message limits
        (`daily_new_contact_limit`, `daily_known_contact_limit`,
        `daily_total_message_limit`, `hourly_message_limit` and
        `minute_message_limit`) can also be raised above their default, up to
        `knobs.<key>.max`.


        Besides the declared responses, this operation returns `422
        limit_out_of_bounds` for one of those five limits outside
        `knobs.<key>.min` to `knobs.<key>.max`, on any line, with the range in
        `error.issues[0].min` and `error.issues[0].max`. That check runs before
        the two rules above: a value above `knobs.<key>.max` returns this `422`,
        not `403 cannot_increase_limit`. It also returns `422
        invalid_activity_curve` for an `activity_curve` that is empty, repeats
        an hour or has a total weight of 0. This operation sends no event.
      parameters:
        - schema:
            type: string
            pattern: ^line_[0-9A-Za-z]{25}$
            description: 'Id of a line: `line_` followed by 25 letters or digits.'
          required: true
          description: 'Id of a line: `line_` followed by 25 letters or digits.'
          name: id
          in: path
      requestBody:
        content:
          application/json:
            schema:
              $ref: '#/components/schemas/LineConfigPatch'
      responses:
        '200':
          description: The configuration of the line after the change.
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/LineConfigEnvelope'
        '400':
          description: >-
            Invalid request. `validation_failed`: an unknown key, a `null`
            value, a value outside the range the schema declares, or a
            `timezone` that is not an IANA time zone name.
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ErrorEnvelope'
        '401':
          description: No valid credential. `error.code` is `unauthorized`.
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ErrorEnvelope'
        '403':
          description: >-
            Refused. `forbidden`: the request carries neither an API key in its
            `Authorization` header nor the header `X-Requested-With:
            XMLHttpRequest`, or the key is line-scoped and this line is outside
            its list. `cannot_increase_limit`: a limit is above its default.
            `cannot_decrease_delay`: a delay is below its default.
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ErrorEnvelope'
        '404':
          description: 'Not found. `not_found`: the line does not exist, or it is not yours.'
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ErrorEnvelope'
        '429':
          description: >-
            Too many requests. `error.code` is `rate_limit_exceeded` when more
            than 100 requests came from the same network address in 60 seconds,
            whatever their API key or account: wait `error.retry_after` seconds.
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ErrorEnvelope'
        '500':
          description: >-
            Unexpected failure. `error.code` is `internal_error`. An operation
            that takes a JSON body also returns it when the body, sent as
            `application/json`, is not valid JSON. Quote `trace_id` when you
            report it to iSnap.
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ErrorEnvelope'
      security:
        - bearerAuth: []
components:
  schemas:
    LineConfigPatch:
      type: object
      properties:
        default_use_typing_indicator:
          type: boolean
          description: >-
            Whether a message that does not state `use_typing_indicator` shows
            the typing indicator before it is sent.
        quota_overflow_behavior:
          type: string
          enum:
            - queue
            - drop
            - fail
          description: >-
            What happens to a send that reaches a sending limit. `queue`: the
            message is accepted and held, with `status: scheduled`. `drop` or
            `fail`: the send returns `429` and nothing is stored; the two values
            behave the same.
        daily_new_contact_limit:
          type: integer
          minimum: 1
          maximum: 500
          description: >-
            Distinct new contacts the line can message per rolling 24 hours.
            Accepted values: 5 to 200. Another integer from 1 to 500 returns
            `422 limit_out_of_bounds`. A value outside 1 to 500, or one that is
            not an integer, returns `400 validation_failed`. It can only be
            lowered below the default (`403 cannot_increase_limit`), except on a
            BYOD line, where it can be raised up to
            `knobs.daily_new_contact_limit.max`.
        daily_known_contact_limit:
          type: integer
          minimum: 1
          maximum: 2000
          description: >-
            Distinct known contacts the line can message per rolling 24 hours.
            Accepted values: 10 to 1,000. Another integer from 1 to 2,000
            returns `422 limit_out_of_bounds`. A value outside 1 to 2,000, or
            one that is not an integer, returns `400 validation_failed`. It can
            only be lowered below the default (`403 cannot_increase_limit`),
            except on a BYOD line, where it can be raised up to
            `knobs.daily_known_contact_limit.max`.
        daily_total_message_limit:
          type: integer
          minimum: 1
          maximum: 100000
          description: >-
            Messages the line can send per rolling 24 hours. Accepted values: 10
            to 1,000. Another integer from 1 to 100,000 returns `422
            limit_out_of_bounds`. A value outside 1 to 100,000, or one that is
            not an integer, returns `400 validation_failed`. It can only be
            lowered below the default (`403 cannot_increase_limit`), except on a
            BYOD line, where it can be raised up to
            `knobs.daily_total_message_limit.max`.
        hourly_message_limit:
          type: integer
          minimum: 1
          maximum: 1000
          description: >-
            Messages the line can send per rolling 60 minutes. Accepted values:
            5 to 200. Another integer from 1 to 1,000 returns `422
            limit_out_of_bounds`. A value outside 1 to 1,000, or one that is not
            an integer, returns `400 validation_failed`. It can only be lowered
            below the default (`403 cannot_increase_limit`), except on a BYOD
            line, where it can be raised up to `knobs.hourly_message_limit.max`.
        minute_message_limit:
          type: integer
          minimum: 1
          maximum: 100
          description: >-
            Messages the line can send per rolling 60 seconds. Accepted values:
            1 to 60. An integer from 61 to 100 returns `422
            limit_out_of_bounds`. A value outside 1 to 100, or one that is not
            an integer, returns `400 validation_failed`. It can only be lowered
            below the default (`403 cannot_increase_limit`), except on a BYOD
            line, where it can be raised up to `knobs.minute_message_limit.max`.
        min_inter_message_seconds:
          type: integer
          minimum: 1
          maximum: 300
          description: >-
            Minimum number of seconds between two messages of the line. Accepted
            values: 1 to 300. It can only be raised above the default (`403
            cannot_decrease_delay`).
        min_inter_new_contact_seconds:
          type: integer
          minimum: 30
          maximum: 3600
          description: >-
            Minimum number of seconds between two first messages to new
            contacts. Accepted values: 30 to 3,600. It can only be raised above
            the default (`403 cannot_decrease_delay`).
        max_queue_depth:
          type: integer
          minimum: 10
          maximum: 5000
          description: >-
            Maximum number of held messages on the line: beyond it, a send that
            would be held returns `429 queue_full`. Accepted values: 10 to
            5,000. It can only be lowered below the default (`403
            cannot_increase_limit`).
        reply_window_hours:
          type: integer
          minimum: 1
          maximum: 168
          description: >-
            Reply lane: a message qualifies as a reply when its recipient
            messaged the line within this number of hours. Accepted values: 1 to
            168. It can only be lowered below the default (`403
            cannot_increase_limit`).
        reply_max_per_inbound:
          type: integer
          minimum: 0
          maximum: 50
          description: >-
            Reply lane: the number of messages to a contact that qualify as
            replies after each message from that contact. 0 turns the reply lane
            off. Accepted values: 0 to 50. It can only be lowered below the
            default (`403 cannot_increase_limit`).
        daily_reply_limit:
          type: integer
          minimum: 0
          maximum: 1000
          description: >-
            Reply-lane allowance: the number of replies per rolling 24 hours
            that can pass a sending limit through the reply lane. 0 turns the
            reply lane off. Accepted values: 0 to 1,000. It can only be lowered
            below the default (`403 cannot_increase_limit`).
        timezone:
          type: string
          description: >-
            IANA time zone name of the line, for example `America/New_York`
            (`400 validation_failed` otherwise). iSnap reads quiet hours in it
            for a recipient whose own time zone it does not know. Once set, it
            can be replaced but not removed.
        activity_curve:
          type: array
          items:
            type: object
            properties:
              hour:
                type: integer
                minimum: 0
                maximum: 23
                description: >-
                  Hour of the day, from 0 to 23, in the local time of the
                  recipient.
              weight:
                type: integer
                minimum: 0
                description: >-
                  Weight of this hour, a non-negative integer. 0 makes it a
                  quiet hour; a larger weight gives the hour a larger share of
                  the held messages.
            required:
              - hour
              - weight
          description: >-
            The sending hours of the line, as a list of hours with a weight. An
            hour with weight 0, or with no entry, is a quiet hour: a message
            accepted then is held until the next hour that has a weight.
            Messages held by a 24-hour sending limit are placed in the hours in
            proportion to their weights. It needs at least one entry, no hour
            twice, and a total weight above 0 (`422 invalid_activity_curve`
            otherwise). A curve the same as `default_activity_curve` (returned
            by `GET /v1/lines/{id}/config`) removes the override instead of
            setting one. Two curves are the same when every hour from 0 to 23
            has the same weight in both, an hour with no entry counting as 0:
            the order of the entries does not matter, and a curve that lists
            only its weighted hours is the same as the 24-hour curve with 0
            everywhere else.
      additionalProperties: false
      description: >-
        The keys to override on this line. Send a key with its default value to
        remove its override. `null` and unknown keys return `400
        validation_failed`.
    LineConfigEnvelope:
      type: object
      properties:
        success:
          type: boolean
          enum:
            - true
          description: Always `true` on a success response.
        data:
          $ref: '#/components/schemas/LineConfigResponseData'
        trace_id:
          type: string
          description: >-
            Trace id of the request that produced this response: 32 lowercase
            hexadecimal characters. Quote it when you report a problem to iSnap.
        request_id:
          type: string
          description: >-
            Id of the request that produced this response: `req_` followed by 25
            letters or digits.
      required:
        - success
        - data
        - trace_id
        - request_id
    ErrorEnvelope:
      type: object
      properties:
        success:
          type: boolean
          enum:
            - false
          description: Always `false` on an error response.
        data:
          nullable: true
          description: Always `null` on an error response.
        error:
          type: object
          properties:
            status:
              type: integer
              description: The HTTP status of the response.
            code:
              type: string
              description: >-
                Stable machine-readable code that names the refusal. Branch on
                this value.
            message:
              type: string
              description: >-
                Text for a person. It can change between versions: do not branch
                on it.
            retry_after:
              type: integer
              nullable: true
              description: >-
                Seconds to wait before the next attempt. Set on the `429`
                responses that know a delay, where the `Retry-After` header
                carries the same value. When it is above 60 seconds, do not wait
                in a request: schedule the call, or report the time. `null` on
                every other error.
            retry_at:
              type: string
              nullable: true
              description: >-
                ISO 8601 timestamp at which the refusal ends. Set only on `429
                rebind_cap_reached`. `null` on every other error.
            issues:
              type: array
              nullable: true
              items:
                type: object
                properties:
                  path:
                    type: array
                    items:
                      anyOf:
                        - type: string
                        - type: number
                    description: >-
                      Where the problem is: the field names and array indexes
                      that lead to it.
                  message:
                    type: string
                    description: Text for a person.
                  code:
                    type: string
                    description: >-
                      Kind of problem. On `validation_failed`, for example
                      `invalid_type`, `invalid_value`, `invalid_format`,
                      `invalid_union`, `invalid_key`, `invalid_element`,
                      `too_small`, `too_big`, `not_multiple_of`,
                      `unrecognized_keys` or `custom`. The list is open: read
                      `path` and `message`.
                  min:
                    type: integer
                    description: >-
                      Smallest accepted value. Present only on
                      `limit_out_of_bounds`, `mac_quantity_not_a_pack`,
                      `byop_reduction_strands_mac_sessions` and
                      `byop_reduction_strands_byod_lines`.
                  max:
                    type: integer
                    description: >-
                      Largest accepted value. Present only on
                      `limit_out_of_bounds` and
                      `mac_sessions_exceed_byop_lines`, and on the `too_big`
                      issue of an `Idempotency-Key` header longer than 255
                      characters.
                required:
                  - path
                  - message
                  - code
              description: >-
                Problems found in the request, one entry each. Set on most `400
                validation_failed` responses and on the refusals that name a
                field: a refused `handle` of `POST /v1/lookup` has `issues:
                null`. `null` on every other error.
          required:
            - status
            - code
            - message
            - retry_after
            - retry_at
            - issues
          description: >-
            What went wrong. The six fields are always present; `retry_after`,
            `retry_at` and `issues` are `null` when they do not apply.
        trace_id:
          type: string
          description: >-
            Trace id of the request that produced this response: 32 lowercase
            hexadecimal characters. Quote it when you report a problem to iSnap.
        request_id:
          type: string
          description: >-
            Id of the request that produced this response: `req_` followed by 25
            letters or digits.
      required:
        - success
        - data
        - error
        - trace_id
        - request_id
      description: The body of an error response.
    LineConfigResponseData:
      type: object
      properties:
        line_id:
          type: string
          pattern: ^line_[0-9A-Za-z]{25}$
          description: 'Id of a line: `line_` followed by 25 letters or digits.'
        config:
          $ref: '#/components/schemas/EffectiveLineConfig'
        overridden_keys:
          type: array
          items:
            type: string
          description: The keys of `config` that have an override on this line.
        knobs:
          $ref: '#/components/schemas/LineConfigKnobs'
        default_activity_curve:
          type: array
          items:
            type: object
            properties:
              hour:
                type: integer
                minimum: 0
                maximum: 23
                description: >-
                  Hour of the day, from 0 to 23, in the local time of the
                  recipient.
              weight:
                type: integer
                minimum: 0
                description: >-
                  Weight of this hour, a non-negative integer. 0 makes it a
                  quiet hour; a larger weight gives the hour a larger share of
                  the held messages.
            required:
              - hour
              - weight
          description: >-
            The sending hours the line has without an `activity_curve` override,
            as a list of hours with a weight. Never empty. It depends on whether
            the line is an iMessage line or an Android line, and iSnap can
            change it: read it here instead of storing it. Send it as
            `activity_curve` in `PATCH /v1/lines/{id}/config` to remove the
            override.
      required:
        - line_id
        - config
        - overridden_keys
        - knobs
        - default_activity_curve
      description: The sending configuration of a line.
    EffectiveLineConfig:
      type: object
      properties:
        default_use_typing_indicator:
          type: boolean
          description: >-
            Whether a message that does not state `use_typing_indicator` shows
            the typing indicator before it is sent.
        quota_overflow_behavior:
          type: string
          enum:
            - queue
            - drop
            - fail
          description: >-
            What happens to a send that reaches a sending limit. `queue`: the
            message is accepted and held, with `status: scheduled`. `drop` or
            `fail`: the send returns `429` and nothing is stored; the two values
            behave the same.
        daily_new_contact_limit:
          type: integer
          minimum: 0
          description: Distinct new contacts the line can message per rolling 24 hours.
        daily_known_contact_limit:
          type: integer
          minimum: 0
          description: Distinct known contacts the line can message per rolling 24 hours.
        daily_total_message_limit:
          type: integer
          minimum: 0
          description: Messages the line can send per rolling 24 hours.
        hourly_message_limit:
          type: integer
          minimum: 0
          description: Messages the line can send per rolling 60 minutes.
        minute_message_limit:
          type: integer
          minimum: 0
          description: Messages the line can send per rolling 60 seconds.
        min_inter_message_seconds:
          type: integer
          minimum: 0
          description: Minimum number of seconds between two messages of the line.
        min_inter_new_contact_seconds:
          type: integer
          minimum: 0
          description: >-
            Minimum number of seconds between two first messages to new
            contacts.
        max_queue_depth:
          type: integer
          minimum: 0
          description: >-
            Maximum number of held messages on the line: beyond it, a send that
            would be held returns `429 queue_full`.
        reply_window_hours:
          type: integer
          minimum: 0
          description: >-
            Reply lane: a message qualifies as a reply when its recipient
            messaged the line within this number of hours.
        reply_max_per_inbound:
          type: integer
          minimum: 0
          description: >-
            Reply lane: the number of messages to a contact that qualify as
            replies after each message from that contact. 0 means the reply lane
            is off.
        daily_reply_limit:
          type: integer
          minimum: 0
          description: >-
            Reply-lane allowance: the number of replies per rolling 24 hours
            that can pass a sending limit through the reply lane. 0 means the
            reply lane is off.
        timezone:
          type: string
          description: >-
            IANA time zone of the line. Without an override, iSnap derives it
            from the North American area code of the line, else from its country
            when that country has a single time zone; otherwise it is
            `Europe/London` for a `+44` number and `America/Chicago` for any
            other number.
        activity_curve:
          type: array
          items:
            type: object
            properties:
              hour:
                type: integer
                minimum: 0
                maximum: 23
                description: >-
                  Hour of the day, from 0 to 23, in the local time of the
                  recipient.
              weight:
                type: integer
                minimum: 0
                description: >-
                  Weight of this hour, a non-negative integer. 0 makes it a
                  quiet hour; a larger weight gives the hour a larger share of
                  the held messages.
            required:
              - hour
              - weight
          description: >-
            The sending hours in force on the line, as a list of hours with a
            weight: the override of the line where it has one,
            `default_activity_curve` otherwise. Never empty. An hour with weight
            0, or with no entry, is a quiet hour.
      required:
        - default_use_typing_indicator
        - quota_overflow_behavior
        - daily_new_contact_limit
        - daily_known_contact_limit
        - daily_total_message_limit
        - hourly_message_limit
        - minute_message_limit
        - min_inter_message_seconds
        - min_inter_new_contact_seconds
        - max_queue_depth
        - reply_window_hours
        - reply_max_per_inbound
        - daily_reply_limit
        - timezone
        - activity_curve
      description: >-
        The value in force for every key of the configuration: the override of
        the line where it has one, the default otherwise.
    LineConfigKnobs:
      type: object
      properties:
        daily_new_contact_limit:
          $ref: '#/components/schemas/LineConfigKnobBounds'
        daily_known_contact_limit:
          $ref: '#/components/schemas/LineConfigKnobBounds'
        daily_total_message_limit:
          $ref: '#/components/schemas/LineConfigKnobBounds'
        hourly_message_limit:
          $ref: '#/components/schemas/LineConfigKnobBounds'
        minute_message_limit:
          $ref: '#/components/schemas/LineConfigKnobBounds'
        reply_window_hours:
          $ref: '#/components/schemas/LineConfigKnobBounds'
        reply_max_per_inbound:
          $ref: '#/components/schemas/LineConfigKnobBounds'
        daily_reply_limit:
          $ref: '#/components/schemas/LineConfigKnobBounds'
      required:
        - daily_new_contact_limit
        - daily_known_contact_limit
        - daily_total_message_limit
        - hourly_message_limit
        - minute_message_limit
        - reply_window_hours
        - reply_max_per_inbound
        - daily_reply_limit
      description: >-
        The eight limits that have a default and bounds: the five message limits
        and the three reply limits. Each has its value in force, its default and
        its bounds `min` and `max`. A value above `default` is accepted only for
        the five message limits of a BYOD line, up to `max`.
    LineConfigKnobBounds:
      type: object
      properties:
        current:
          type: integer
          minimum: 0
          description: The value in force on the line.
        default:
          type: integer
          minimum: 0
          description: >-
            The default value. It depends on whether the line is an iMessage
            line or an Android line, and iSnap can change it.
        min:
          type: integer
          minimum: 0
          description: The smallest value the API accepts for this key.
        max:
          type: integer
          minimum: 0
          description: >-
            The upper bound of this key. A value above `default` is accepted, up
            to `max`, only on a BYOD line and only for
            `daily_new_contact_limit`, `daily_known_contact_limit`,
            `daily_total_message_limit`, `hourly_message_limit` and
            `minute_message_limit`. On any other line, and for the three reply
            limits on every line, a value above `default` returns `403
            cannot_increase_limit`. A value above `max` is refused first, on
            every line, with `422 limit_out_of_bounds` or `400
            validation_failed`.
      required:
        - current
        - default
        - min
        - max
      description: >-
        One limit of the line: the value in force, its default, and its bounds.
        A value above the default is accepted only for the five message limits
        of a BYOD line.
  securitySchemes:
    bearerAuth:
      type: http
      scheme: bearer
      description: >-
        An API key created in the iSnap dashboard, or a trial key, sent as
        `Authorization: Bearer <key>`. An API key starts with `isnap_live_` or
        `isnap_test_`; both act on the same account, lines and billing. A trial
        key acts on its trial only.

````

This documentation is built and hosted on [Mintlify](https://mintlify.com), a developer documentation platform.