---
title: "Get a text"
method: GET
path: "/v1/sms/{id}"
tags: ["sms"]
---

# Get a text

`GET /v1/sms/{id}`

## Request

- Base URL: `https://api.mailfixture.com`
- URL: `https://api.mailfixture.com/v1/sms/{id}`
- Auth: HTTP bearer

## Path parameters

- `id` string, uuid, required

## Response `200`

The text with its extraction results.

- SmsDetail
  - `expires_at` string, date-time, required
  - `extracted` Extracted, required: Extraction results computed at receipt. `text`, `auth`, and `spam` are conditionally present keys — see their descriptions.
    - `auth` ExtractedAuth: Receive-side SPF/DKIM/DMARC verdicts (RFC 8601 vocabulary). The whole key is absent when verification is disabled on the deployment — absence means "not verified", never "failed". Observation only: verdicts never affect acceptance.
      - `dkim` DkimAuth[], required: One entry per DKIM signature; unsigned mail is an empty array.
        - `domain` string, required
        - `error` string: Present only for non-pass results — e.g. a body-hash mismatch reports `neutral` with the reason here (RFC 6376 §6.1).
        - `result` 'pass' | 'fail' | 'softfail' | 'neutral' | 'none' | 'temperror' | 'permerror', required: RFC 8601 result vocabulary. DNS trouble degrades to `temperror`.
        - `selector` string, required
      - `dmarc` DmarcAuth, required
        - `domain` string: RFC5322.From domain; present only when non-empty.
        - `policy` 'none' | 'quarantine' | 'reject': Present only when a DMARC record exists.
        - `result` 'pass' | 'fail' | 'softfail' | 'neutral' | 'none' | 'temperror' | 'permerror', required: RFC 8601 result vocabulary. DNS trouble degrades to `temperror`.
      - `spf` SpfAuth, required
        - `domain` string, required: The identity checked (MAIL FROM, falling back to HELO); may be empty.
        - `result` 'pass' | 'fail' | 'softfail' | 'neutral' | 'none' | 'temperror' | 'permerror', required: RFC 8601 result vocabulary. DNS trouble degrades to `temperror`.
    - `links` ExtractedLink[], required
      - `class` 'verify' | 'reset' | 'unsubscribe' | 'other', required: Class guess from URL path + anchor keywords; magic-link/login URLs class as `verify`.
      - `text` string, nullable, required: Anchor text; null for bare-text URLs.
      - `url` string, required
    - `otp` ExtractedOtp, required
      - `best` string, nullable, required: Top-ranked code, or null when no candidate scores above the confidence threshold.
      - `candidates` OtpCandidate[], required: At most 5, sorted by descending score.
        - `score` number, required: Keyword-proximity score, one decimal.
        - `value` string, required: The digit sequence.
    - `spam` ExtractedSpam: SpamAssassin content analysis (local rules only — no network/RBL tests, so scores are deterministic). The whole key is absent when scoring is disabled, the daemon was unreachable, or the message exceeded the scoring size cap — absence means "not scored", never "failed". Observation only: the verdict never affects acceptance.
      - `rules` SpamRule[], required: The rules that fired, with their individual score contributions; empty when nothing matched.
        - `description` string, nullable: Human-readable rule description, when spamd supplied one.
        - `name` string, required: SpamAssassin rule symbol, e.g. `MISSING_HEADERS`.
        - `score` number, required: This rule's contribution to the total; may be negative.
      - `score` number, required: Total SpamAssassin score; higher is spammier. May be negative.
      - `threshold` number, required: The score at or above which the message is classed spam (default 5.0).
      - `verdict` 'spam' | 'ham', required: SpamAssassin's own decision (its `Spam: True/False`), not a client-side threshold recomputation.
    - `text` string: Plain-text rendering of the HTML part; present only when the message had no text/plain part.
  - `from_number` string, required
  - `id` string, uuid, required
  - `phone_number_id` string, uuid, required
  - `received_at` string, date-time, required
  - `text` string, required
  - `to_number` string, required

## Other responses

- `401`: Missing bearer token, malformed key, or unknown/revoked/invalid API key.
- `404`: No such SMS on this account.
- `429`: Per-key rate limit exceeded. `Retry-After` says when the next request will be admitted; the RateLimit headers name the bucket that refused (`requests` or `creates`) with `r=0`.
- `500`: Unexpected server error. `detail` is null — internals are never leaked.

---

[API](https://skmtc.dev/mailfixture/apis/mailfixture-api.md) · [All operations](https://skmtc.dev/mailfixture/apis/mailfixture-api/llms.txt) · [OpenAPI document](https://skmtc.dev/mailfixture/apis/mailfixture-api/revisions/4ddefe29f6f6?raw)
