Mastodon instance blocks are server-wide federation rules for a remote server domain. They help administrators respond when spam, abuse, policy violations, or unsafe moderation patterns are coming from one ActivityPub server rather than one account.

The Mastodon Admin API creates the same kind of domain block that appears under PreferencesModerationFederation in the web admin area. An API token from a user with Manage Federation permission can create the block, and the saved record shows the domain, severity, media and report handling, comments, and public obfuscation setting.

Choose the severity before saving the block. silence is the API value behind a limited server block, while suspend rejects incoming data from the remote domain and removes existing follow relationships with local accounts. Domain blocks apply when LIMITED_FEDERATION_MODE is disabled; allow-listed federation uses domain allows instead of domain blocks.

Steps to block a Mastodon instance with the Admin API:

  1. Confirm the remote domain and block severity.
    API value Moderation effect
    noop Keeps a domain block record without limiting accounts; use it when only media or reports should be rejected.
    silence Limits accounts from the remote domain, hiding their posts by default and turning follows from that server into follow requests.
    suspend Rejects incoming data from the remote domain and removes existing follow relationships with local accounts.
  2. Use an admin user token with Manage Federation permission and the admin:write:domain_blocks scope.

    Replace MASTODON_ACCESS_TOKEN in the requests with the real token value. Add admin:read:domain_blocks if the same token will verify the saved block.
    Related: How to create a Mastodon access token

  3. Create the domain block.
    $ curl --request POST "https://social.example.com/api/v1/admin/domain_blocks" \
      --header "Authorization: Bearer MASTODON_ACCESS_TOKEN" \
      --form "domain=spam.example.net" \
      --form "severity=suspend" \
      --form "reject_media=true" \
      --form "reject_reports=true" \
      --form "private_comment=Coordinated spam reports reviewed by moderators" \
      --form "public_comment=Coordinated spam"
    {
      "id": "127",
      "domain": "spam.example.net",
      "digest": "1f8c0d6aaeb9c2ad33e35f6eaa40c4bfe6fd0d47f768e72486f9a7d5f9fc4b1d",
      "created_at": "2026-06-27T08:20:41.329Z",
      "severity": "suspend",
      "reject_media": true,
      "reject_reports": true,
      "private_comment": "Coordinated spam reports reviewed by moderators",
      "public_comment": "Coordinated spam",
      "obfuscate": false
    }

    severity=suspend cuts federation more aggressively than severity=silence. Existing follow relationships with the suspended server are removed and are not restored automatically if the block is lifted later.

  4. Check the returned domain block fields.

    domain must match the remote server, severity must match the moderation decision, and reject_media or reject_reports should show true only when those additional restrictions were intended. Keep public_comment suitable for display if the instance publishes moderated-server information.

  5. Update the existing record instead of creating a duplicate if the API reports an existing block.
    {
      "error": "You have already imposed stricter limits on spam.example.net.",
      "existing_domain_block": {
        "id": "127",
        "domain": "spam.example.net",
        "severity": "suspend",
        "reject_media": true,
        "reject_reports": true
      }
    }

    A stricter parent-domain block can already cover a subdomain. Use the returned id with PUT /api/v1/admin/domain_blocks/:id when the moderation decision is to adjust comments, media rejection, report rejection, or severity.

  6. Verify the saved domain block from the admin list.
    $ curl --request GET "https://social.example.com/api/v1/admin/domain_blocks" \
      --header "Authorization: Bearer MASTODON_ACCESS_TOKEN"
    [
      {
        "id": "127",
        "domain": "spam.example.net",
        "digest": "1f8c0d6aaeb9c2ad33e35f6eaa40c4bfe6fd0d47f768e72486f9a7d5f9fc4b1d",
        "created_at": "2026-06-27T08:20:41.329Z",
        "severity": "suspend",
        "reject_media": true,
        "reject_reports": true,
        "private_comment": "Coordinated spam reports reviewed by moderators",
        "public_comment": "Coordinated spam",
        "obfuscate": false
      }
    ]