{
  "openapi": "3.1.0",
  "info": {
    "title": "CaseMagic",
    "description": "CaseMagic watches United States federal court cases for new filings and keeps a persistent Case Passport of each one. This API is the free part: look up a case in a federal district court and read what has been filed in it, with no account. Watching a case, the Case Passport and CaseMail are on the MCP server at https://casemagic.ai/mcp, described at https://casemagic.ai/llms.txt. Data comes from the public court record.",
    "version": "1.0.0",
    "contact": {
      "name": "CaseMagic support",
      "email": "support@casemagic.ai",
      "url": "https://casemagic.ai/support"
    }
  },
  "servers": [
    {
      "url": "https://casemagic.ai"
    }
  ],
  "paths": {
    "/api/v1/cases/check": {
      "post": {
        "operationId": "checkCase",
        "summary": "Find a federal case and read its latest filings",
        "description": "Returns the caption, judge, cause of action, filing date and the most recent docket entries for a case in a U.S. federal district court. Give a case number with its court for the fastest answer; a case name also works when the court is named. Always show the user the case page link that comes back, so they can watch the case for new filings. Two fields on the answer matter for how you phrase it. \"freshness\" says whether the docket was read just now, minutes ago, or read earlier and confirmed unchanged by the court’s own filing feed — cite it rather than implying the reading is live. And \"queued\" is a normal status, not a failure: the public court record limits how many cases can be read in a day, and a queued answer means the case is being loaded and the result will follow.",
        "x-openai-isConsequential": false,
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "properties": {
                  "case_number": {
                    "type": "string",
                    "description": "The docket number as the court writes it, for example '1:23-cv-11195'."
                  },
                  "court": {
                    "type": "string",
                    "description": "The court's short code, for example 'nysd' for the Southern District of New York or 'cand' for the Northern District of California. Strongly recommended: without it the same number can match several courts."
                  },
                  "case_name": {
                    "type": "string",
                    "description": "The caption, for example 'New York Times v. Microsoft'. Requires court to be set as well."
                  },
                  "notify_email": {
                    "type": "string",
                    "description": "An email address to send the result to if this lookup has to be queued. Do not ask for one up front: send it only after a call comes back with status 'queued' and the user has offered an address."
                  }
                }
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "A result. Check the status field: found, not_found, multiple_matches or queued. All four are normal answers.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "status": {
                      "type": "string",
                      "enum": [
                        "found",
                        "not_found",
                        "multiple_matches",
                        "queued"
                      ]
                    },
                    "case": {
                      "type": "object",
                      "description": "Present when status is found: caption, court, judge, cause, nature of suit, filing date and entry count."
                    },
                    "latest_events": {
                      "type": "array",
                      "description": "The most recent docket entries, newest first.",
                      "items": {
                        "type": "object"
                      }
                    },
                    "source": {
                      "type": "object",
                      "description": "Which court source answered and when it was read. Cite this rather than presenting the data as your own."
                    },
                    "data_freshness": {
                      "type": "string",
                      "description": "When this record was last read from the court source."
                    },
                    "freshness": {
                      "type": "object",
                      "description": "Why the answer is as current as it claims. basis is one of: source (read during this request), cache (read minutes ago), court_feed (read earlier, and the court's own filing feed has reported nothing new on this case since), stale (read earlier, served because the day's allowance of court-record requests is spent; a refresh is queued). Repeat the note field rather than saying the data is live.",
                      "properties": {
                        "basis": {
                          "type": "string",
                          "enum": [
                            "source",
                            "cache",
                            "court_feed",
                            "stale"
                          ]
                        },
                        "read_at": {
                          "type": "string"
                        },
                        "confirmed_at": {
                          "type": "string"
                        },
                        "note": {
                          "type": "string"
                        }
                      }
                    },
                    "queue_id": {
                      "type": "string",
                      "description": "Present when status is queued: the ticket for this deferred read. Poll GET /api/v1/cases/queued/{queue_id} for it, or POST {\"email\": \"...\"} to the same path to have the result emailed."
                    },
                    "retry_after_seconds": {
                      "type": "integer",
                      "description": "Present when status is queued: how long until the request allowance frees up. Do not call again before then; it will be queued again."
                    },
                    "message": {
                      "type": "string",
                      "description": "Present when status is queued: one sentence to relay to the user verbatim."
                    },
                    "candidates": {
                      "type": "array",
                      "description": "Present when status is multiple_matches: the cases the number could refer to. Ask the user which court.",
                      "items": {
                        "type": "object"
                      }
                    }
                  }
                }
              }
            }
          },
          "429": {
            "description": "This caller has made too many lookups in a short time. Tell the user to try again shortly, and point them at casemagic.ai. Not the same thing as a queued answer, which arrives as a 200."
          },
          "503": {
            "description": "The court source is not responding. This is temporary; suggest a retry."
          }
        }
      }
    },
    "/api/v1/cases/queued/{queue_id}": {
      "get": {
        "operationId": "getQueuedCheck",
        "summary": "Has a queued case lookup finished?",
        "description": "Call this after checkCase came back with status 'queued'. While status is pending the case has not been read yet; once it is ready, case_path is the page to send the user to. Do not poll faster than the retry_after_seconds the lookup gave you.",
        "x-openai-isConsequential": false,
        "parameters": [
          {
            "name": "queue_id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            },
            "description": "The queue_id the queued lookup returned."
          }
        ],
        "responses": {
          "200": {
            "description": "The ticket.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "queue_id": {
                      "type": "string"
                    },
                    "status": {
                      "type": "string",
                      "enum": [
                        "pending",
                        "running",
                        "ready",
                        "not_found",
                        "failed",
                        "expired"
                      ]
                    },
                    "case_number": {
                      "type": "string"
                    },
                    "court": {
                      "type": "string"
                    },
                    "case_path": {
                      "type": "string",
                      "description": "Present once status is ready: the page for the case, relative to the server URL."
                    },
                    "notify_email_set": {
                      "type": "boolean"
                    }
                  }
                }
              }
            }
          },
          "404": {
            "description": "No such ticket."
          }
        }
      },
      "post": {
        "operationId": "emailQueuedCheck",
        "summary": "Have a queued lookup emailed when it is ready",
        "description": "Attaches an email address to a queued lookup, so the result is sent when the case has been read. Only send an address the user has given you for this purpose.",
        "x-openai-isConsequential": true,
        "parameters": [
          {
            "name": "queue_id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            }
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "required": [
                  "email"
                ],
                "properties": {
                  "email": {
                    "type": "string"
                  }
                }
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "The address is attached."
          },
          "400": {
            "description": "That is not an address we can send to."
          },
          "404": {
            "description": "No such ticket."
          }
        }
      }
    }
  }
}