> ## 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.

# Remove a reaction

> Removes the line's reaction from a message.

* **Credential:** an API key. A trial key returns `401 unauthorized`. See [Removing a reaction](/guides/conversations#removing-a-reaction).
* **Line-scoped keys:** a [line-scoped key](/authentication#line-scoped-keys) gets `404 not_found` for a message on a line outside its list.
* **Test keys:** a removal sent with an `isnap_test_` account key reaches the real contact: see [Test keys](/authentication#test-keys).
* **`Idempotency-Key`:** honored. The key shares the space of the line with `POST /v1/messages`. See [Retrying a reaction](/guides/conversations#retrying-a-reaction).
* **Events:** sends `reaction.removed` when the line's device confirms the removal. Sends nothing in the other cases.
* **Response:** `removed` is `false` and `type` is `null` when the line had no reaction on the message. `removed: true` does not mean that the reaction left the contact's screen: when the line has no paired device, or when the device fails the removal, nothing reaches the contact.

## Errors

| Status | `error.code` | When |
| - | - | - |
| 400 | `validation_failed` | The id is malformed. |
| 400 | `line_not_active` | The message's line is neither `active` nor `suspended`. |
| 403 | `line_suspended` | The message's line is suspended. |
| 404 | `not_found` | The message is unknown, belongs to another account, or is on a line outside the list of a line-scoped key. |
| 409 | `idempotency_conflict` | The `Idempotency-Key` was already used on this line for another call. |
| 422 | `sms_reactions_not_supported` | The message was sent or received as SMS or RCS. |
| 422 | `multi_attachment_reaction` | The message has more than one attachment. |
| 422 | `parent_not_yet_acked` | The line's device has not confirmed the message, or the message was typed on the line's device. |
| 422 | `reaction_recipient_unsupported` | The contact's handle is longer than 20 characters, as most email addresses are. |

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


## OpenAPI

````yaml DELETE /v1/messages/{id}/reactions
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/messages/{id}/reactions:
    delete:
      summary: Remove a reaction
      description: >-
        Removes the line's reaction from a message. Returns `200` with `removed:
        true` and the `type` removed, or with `removed: false` and `type: null`
        when the line had no reaction on the message.


        `reaction.removed` is sent when the line's device confirms the removal.
        When the line has no paired device, or its device cannot remove
        reactions, the response is still `removed: true`, nothing reaches the
        contact and no event follows. The `reactions` list of the message drops
        the reaction as soon as this request is accepted.


        The message must meet the same conditions as for adding a reaction: an
        iMessage message that the line's device has confirmed, with at most one
        attachment, whose contact handle is 20 characters or fewer, on an
        `active` line. Otherwise the API returns `422` with
        `sms_reactions_not_supported`, `multi_attachment_reaction`,
        `parent_not_yet_acked` or `reaction_recipient_unsupported`.


        Accepts an API key. Send an `Idempotency-Key` header to make a retry
        safe: the same key with the same message returns the first result, and
        the same key with another message or another operation returns `409
        idempotency_conflict`.
      parameters:
        - schema:
            type: string
            pattern: ^msg_[0-9A-Za-z]{25}$
            description: 'Message id: `msg_` followed by 25 letters or digits.'
          required: true
          description: 'Message id: `msg_` followed by 25 letters or digits.'
          name: id
          in: path
      responses:
        '200':
          description: >-
            The result. `removed` is `false` when the line had no reaction on
            the message.
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ReactionRemovalEnvelope'
        '400':
          description: >-
            Invalid request. `error.code` is `validation_failed` (the id is
            malformed) or `line_not_active` (the status of the message's line is
            neither `active` nor `suspended`).
          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. `error.code` is `forbidden` (the request carries neither an
            API key in its `Authorization` header nor the header
            `X-Requested-With: XMLHttpRequest`) or `line_suspended` (the
            message's line is suspended).
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ErrorEnvelope'
        '404':
          description: >-
            Not found. `error.code` is `not_found`: the message does not exist,
            belongs to another account, or is on a line outside the key's
            `line_ids`.
          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:
    ReactionRemovalEnvelope:
      type: object
      properties:
        success:
          type: boolean
          enum:
            - true
          description: Always `true` on a success response.
        data:
          $ref: '#/components/schemas/ReactionRemoval'
        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.
    ReactionRemoval:
      type: object
      properties:
        parent_message_id:
          type: string
          description: Id of the message.
        removed:
          type: boolean
          description: >-
            `true` when the line had a reaction on the message and its removal
            was accepted: it does not mean that the line's device removed it.
            `false` when the line had no reaction on the message.
        type:
          type: string
          nullable: true
          enum:
            - love
            - like
            - dislike
            - laugh
            - emphasize
            - question
            - null
          description: The reaction that was removed. `null` when `removed` is `false`.
      required:
        - parent_message_id
        - removed
        - type
      description: The result of `DELETE /v1/messages/{id}/reactions`.
  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.