animalchecklist-com Sightings API

One person's private checklist. Needs their sync code.

Operations 4

POST /accounts Create an anonymous sync code #
DELETE /accounts Delete an anonymous sync list #
GET /sightings Read one person's sightings #
PUT /sightings Merge sightings #

Work with this as data

Every API here is available over the APIs.io API and to AI agents over MCP.

MCP server

One button, every client — Claude, Cursor, VS Code and the rest.

https://apis.io/mcp

Tools for apis

7 MCP tools reach this
  • find_apisBrowse and filter every API in the catalog.
  • get_api_artifactsOne API's artifacts, grouped by type.
  • get_openapiThe primary OpenAPI for this API.
  • find_similar_apisAPIs that look like this one.
  • apis_io_searchSTART HERE — APIs, providers and tags for one query, each with its total.
  • resolveTurn a domain, URL or GitHub org into the provider it belongs to.
  • find_cohortsEvery scored population of providers in the catalog.
All 92 tools →

Call it yourself

curl for this page
This API
curl "https://apis.io/api/v1/apis/animalchecklist-com:animalchecklist-com-sightings-api"
All apis
curl "https://apis.io/api/v1/apis?limit=25"

Discovery needs no key. Ratings and market analysis are Pro.

Get an API key

Free tier, no form to fill in. Signing in shares your email address with us — we store it to create your key and to recognise you if you sign in with another provider. See our Privacy Policy and Terms.

A second provider on the same verified email joins the account you already have.

OpenAPI Specification

animalchecklist-com-sightings-api-openapi.yml Raw ↑
openapi: 3.2.0
info:
  title: Animal Checklist Sightings API
  version: 1.0.0
  summary: Animal catalogue and account features.
  description: 'Search animals in eight languages and read licensed photos and summaries. Public catalogue reads need no account. Photo recognition and account data require a session. Sightings accept an anonymous sync code or an account session. Accounts use email magic links and passkeys. Versioning: URL path `/api/v1`; a breaking change ships as `/api/v2` and `/api/v1` then answers with Deprecation (RFC 9745) and Sunset (RFC 8594) headers for at least 180 days. Pagination: page and per query parameters, with total, page and per repeated in the answer. Batch: `GET /animals?ids=` reads up to 500 animals in one request. Errors: `{"error":{"code","message"}}`. Check each photo licence and source; summaries are Wikipedia CC BY-SA 4.0; names and counts come from iNaturalist and Wikidata.'
  termsOfService: https://animalchecklist.com/about
  contact:
    name: Animal Checklist
    url: https://animalchecklist.com/for-agents
    email: animalchecklist@arnekellmann.de
  license:
    name: CC BY-SA 4.0 (API description only)
    url: https://creativecommons.org/licenses/by-sa/4.0/
servers:
- url: https://animalchecklist.com/api/v1
  description: Production
security: []
tags:
- name: Sightings
  description: One person's private checklist. Needs their sync code.
paths:
  /accounts:
    post:
      operationId: createAccount
      summary: Create an anonymous sync code
      description: 'Creates one anonymous account and answers its sync code. The code is the only credential and is never shown again. An agent calls this only when the person asked for a sync code, and never stores or prints it. Limit: 20 requests per IP per hour.'
      tags:
      - Sightings
      responses:
        '201':
          description: The new sync code.
          headers:
            RateLimit-Policy:
              $ref: '#/components/headers/RateLimit-Policy'
          content:
            application/json:
              schema:
                type: object
                required:
                - data
                properties:
                  data:
                    type: object
                    required:
                    - code
                    properties:
                      code:
                        type: string
                        pattern: ^AC(-[0-9A-HJKMNP-TV-Z]{4}){4}$
              example:
                data:
                  code: AC-4K7M-2XQ9-T3VZ-8BNR
        '400':
          description: Invalid input.
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/Error'
              example:
                error:
                  code: INVALID_INPUT
                  message: 'page: Number must be at least 1'
        '404':
          description: Not found.
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/Error'
              example:
                error:
                  code: NOT_FOUND
                  message: Unknown animal
        '429':
          description: Rate limited.
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/Error'
              example:
                error:
                  code: RATE_LIMITED
                  message: Too many requests; try again later
          headers:
            Retry-After:
              schema:
                type: integer
              description: Seconds to wait.
            RateLimit-Policy:
              $ref: '#/components/headers/RateLimit-Policy'
        '500':
          description: Unexpected error.
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/Error'
              example:
                error:
                  code: INTERNAL
                  message: Unexpected error
    delete:
      operationId: deleteAnonymousAccount
      summary: Delete an anonymous sync list
      description: Deletes the anonymous account and all server sightings after explicit confirmation. This code cannot delete an email-linked account. The browser clears its local list after a successful response.
      tags:
      - Sightings
      security:
      - syncCode: []
      requestBody:
        required: true
        content:
          application/json:
            schema:
              type: object
              required:
              - confirm
              properties:
                confirm:
                  type: string
                  const: DELETE
            example:
              confirm: DELETE
      responses:
        '204':
          description: Completed without a response body.
        '400':
          description: Invalid input.
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/Error'
              example:
                error:
                  code: INVALID_INPUT
                  message: 'page: Number must be at least 1'
        '401':
          description: Missing or unknown sync code.
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/Error'
              example:
                error:
                  code: UNKNOWN_CODE
                  message: Unknown sync code
        '404':
          description: Not found.
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/Error'
              example:
                error:
                  code: NOT_FOUND
                  message: Unknown animal
        '429':
          description: Rate limited.
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/Error'
              example:
                error:
                  code: RATE_LIMITED
                  message: Too many requests; try again later
          headers:
            Retry-After:
              schema:
                type: integer
              description: Seconds to wait.
            RateLimit-Policy:
              $ref: '#/components/headers/RateLimit-Policy'
        '500':
          description: Unexpected error.
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/Error'
              example:
                error:
                  code: INTERNAL
                  message: Unexpected error
  /sightings:
    get:
      operationId: getSightings
      summary: Read one person's sightings
      description: Answers every sighting stored for the sync code or signed-in account, tombstones included. Private to that person.
      tags:
      - Sightings
      security:
      - syncCode: []
      - sessionCookie: []
      parameters:
      - name: X-Account-Id
        in: header
        required: false
        schema:
          type: string
          format: uuid
        description: Required with session-cookie authentication; omit with a sync code.
      responses:
        '200':
          description: The full list.
          headers:
            Deprecation:
              $ref: '#/components/headers/Deprecation'
            Sunset:
              $ref: '#/components/headers/Sunset'
          content:
            application/json:
              schema:
                type: object
                required:
                - data
                properties:
                  data:
                    type: array
                    items:
                      $ref: '#/components/schemas/Sighting'
              example:
                data:
                - animalId: red-fox
                  seenAt: '2026-05-01T10:00:00.000Z'
                  updatedAt: '2026-05-01T10:00:00.000Z'
                  deleted: false
        '400':
          description: Invalid input.
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/Error'
              example:
                error:
                  code: INVALID_INPUT
                  message: 'page: Number must be at least 1'
        '401':
          description: Missing or unknown sync code.
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/Error'
              example:
                error:
                  code: UNKNOWN_CODE
                  message: Unknown sync code
        '404':
          description: Not found.
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/Error'
              example:
                error:
                  code: NOT_FOUND
                  message: Unknown animal
        '429':
          description: Rate limited.
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/Error'
              example:
                error:
                  code: RATE_LIMITED
                  message: Too many requests; try again later
          headers:
            Retry-After:
              schema:
                type: integer
              description: Seconds to wait.
            RateLimit-Policy:
              $ref: '#/components/headers/RateLimit-Policy'
        '500':
          description: Unexpected error.
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/Error'
              example:
                error:
                  code: INTERNAL
                  message: Unexpected error
    put:
      operationId: putSightings
      summary: Merge sightings
      description: Merges the sent list into the stored list, last writer wins on `updatedAt`, and answers the merged list. Repeating the same body changes nothing, so a retry after a network failure is safe. At most 2000 entries.
      tags:
      - Sightings
      security:
      - syncCode: []
      - sessionCookie: []
      parameters:
      - name: X-Account-Id
        in: header
        required: false
        schema:
          type: string
          format: uuid
        description: Required with session-cookie authentication; omit with a sync code.
      requestBody:
        required: true
        content:
          application/json:
            schema:
              type: object
              required:
              - sightings
              properties:
                sightings:
                  type: array
                  items:
                    $ref: '#/components/schemas/Sighting'
                  maxItems: 2000
            example:
              sightings:
              - animalId: red-fox
                seenAt: '2026-05-01T10:00:00.000Z'
                updatedAt: '2026-05-01T10:00:00.000Z'
                deleted: false
      responses:
        '200':
          description: The merged list.
          headers:
            Deprecation:
              $ref: '#/components/headers/Deprecation'
            Sunset:
              $ref: '#/components/headers/Sunset'
          content:
            application/json:
              schema:
                type: object
                required:
                - data
                properties:
                  data:
                    type: array
                    items:
                      $ref: '#/components/schemas/Sighting'
              example:
                data: []
        '400':
          description: Invalid input.
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/Error'
              example:
                error:
                  code: INVALID_INPUT
                  message: 'page: Number must be at least 1'
        '401':
          description: Missing or unknown sync code.
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/Error'
              example:
                error:
                  code: UNKNOWN_CODE
                  message: Unknown sync code
        '404':
          description: Not found.
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/Error'
              example:
                error:
                  code: NOT_FOUND
                  message: Unknown animal
        '413':
          description: Body too large.
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/Error'
              example:
                error:
                  code: TOO_LARGE
                  message: Request too large
        '429':
          description: Rate limited.
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/Error'
              example:
                error:
                  code: RATE_LIMITED
                  message: Too many requests; try again later
          headers:
            Retry-After:
              schema:
                type: integer
              description: Seconds to wait.
            RateLimit-Policy:
              $ref: '#/components/headers/RateLimit-Policy'
        '500':
          description: Unexpected error.
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/Error'
              example:
                error:
                  code: INTERNAL
                  message: Unexpected error
components:
  schemas:
    Sighting:
      type: object
      title: Sighting
      required:
      - animalId
      - seenAt
      - updatedAt
      - deleted
      properties:
        animalId:
          type: string
          pattern: ^[a-z0-9]+(-[a-z0-9]+)*$
          description: Slug of the animal taxon, for example `red-fox`.
          examples:
          - red-fox
        seenAt:
          type: string
          format: date-time
        updatedAt:
          type: string
          format: date-time
          description: Merge key, last writer wins.
        deleted:
          type: boolean
          description: Tombstone. Other devices drop the row.
    Error:
      type: object
      title: Error
      description: Every failure answers this shape. The status matches `error.code`.
      required:
      - error
      properties:
        error:
          type: object
          required:
          - code
          - message
          properties:
            code:
              type: string
              enum:
              - INVALID_INPUT
              - INVALID_JSON
              - UNKNOWN_CODE
              - UNKNOWN_ANIMAL
              - CANDIDATE_UNAVAILABLE
              - CANDIDATE_IMAGE_UNAVAILABLE
              - AUTH_REQUIRED
              - INVALID_ORIGIN
              - INVALID_BODY
              - INVALID_EMAIL
              - EMAIL_UNAVAILABLE
              - INVALID_LINK
              - INVALID_PASSKEY
              - INVALID_CHALLENGE
              - PASSKEY_LIMIT
              - PASSKEY_UNAVAILABLE
              - PASSKEY_NOT_FOUND
              - ACCOUNT_SWITCH_REQUIRED
              - ACCOUNT_LINKED
              - QUIZ_UNAVAILABLE
              - QUIZ_NOT_FOUND
              - QUIZ_EXPIRED
              - QUIZ_INCOMPLETE
              - QUIZ_ALREADY_SAVED
              - INVALID_ANSWER
              - QUIZ_ORDER
              - QUIZ_ANSWERED
              - MCP_KEY_LIMIT
              - NOT_FOUND
              - TOO_LARGE
              - RATE_LIMITED
              - INTERNAL
              description: Machine-readable reason.
            message:
              type: string
              description: One sentence for a human.
  headers:
    Sunset:
      schema:
        type: string
        format: http-date
      description: RFC 8594. Date the deprecated version stops answering.
    RateLimit-Policy:
      schema:
        type: string
      description: Quota policy of a metered endpoint, for example "accounts";q=20;w=3600.
    Deprecation:
      schema:
        type: string
      description: RFC 9745. Present on every answer of a deprecated version.
  securitySchemes:
    syncCode:
      type: http
      scheme: bearer
      bearerFormat: AC-XXXX-XXXX-XXXX-XXXX
      description: The person's anonymous sync code. It grants read and write access to that one checklist and nothing else. An agent uses a code only when the person supplied it.
    quizRound:
      type: http
      scheme: bearer
      bearerFormat: 43-character opaque round secret
      description: Keep this secret in local storage. Completed guest rounds remain claimable until deletion.
    sessionCookie:
      type: apiKey
      in: cookie
      name: ac_session
      description: HttpOnly session set after a magic link or passkey sign-in.
externalDocs:
  description: Agent guide
  url: https://animalchecklist.com/for-agents
x-authentication:
  scheme: public reads; sync code or session for sightings; session for recognition and account data
  description: Catalogue reads need no key or account. Sightings accept a sync code or the person's session cookie. Recognition, account and passkey management require a session cookie.
  docs: https://animalchecklist.com/for-agents
x-versioning-policy:
  scheme: url-path
  current: v1
  deprecation: A breaking change ships as a new path version. The old version answers with a Deprecation header (RFC 9745) and a Sunset header (RFC 8594) at least 180 days before removal.
  headers:
  - Deprecation
  - Sunset
  noticePeriodDays: 180
  docs: https://animalchecklist.com/for-agents
x-pagination:
  style: page
  description: Send `page` from 1 and `per` up to 120 for animals or 100 for registry endpoints. Default per is 60. Stop when page * per >= total.
  requestParameters:
  - page
  - per
  responseFields:
  - total
  - page
  - per
  endpoints:
  - /animals
  - /taxa
  - /breeds
x-batch-endpoints:
- path: /animals
  method: get
  operationId: getAnimalsByIds
  itemsField: ids
  maxItems: 500
  description: Reads up to 500 animals in one request with a comma separated `ids` list.
- path: /sightings
  method: put
  operationId: putSightings
  itemsField: sightings
  maxItems: 2000
  description: Merges up to 2000 sightings in one request.
x-rate-limit:
  description: Public catalogue reads use edge caching. POST /accounts allows 20 requests per IP per hour. POST /recognitions allows 10 per IP per hour, 20 per account per day, and 200 total per day. POST /client-error allows 30 per IP per hour.
  headers:
  - RateLimit-Policy
  - Retry-After
  accountsPerHour: 20
  clientErrorPerHour: 30
x-llms-txt: https://animalchecklist.com/llms.txt
x-agents-md: https://animalchecklist.com/agents.md
x-api-catalog: https://animalchecklist.com/.well-known/api-catalog
x-licence:
  scope: The info.license covers this API description. Response content keeps its source rights.
  terms: https://animalchecklist.com/licences
  photos: CC0, Public domain, Pexels License or Pixabay Content License; see each image record
  texts: Wikipedia excerpts, CC BY-SA 4.0. Keep attribution, licence link, changes and supplied notices. Check article exceptions.
  data: 'Structured Wikidata: CC0. iNaturalist taxonomy archive: no explicit licence supplied. Breed standards: source-specific rights.'