Mr. Doge
Reference

Images

Public CDN endpoints for team and region logos, cached, immutable, no auth required.

The Mr. Doge platform serves team and region logos at stable public URLs. No API key, no auth header, no SDK call. Render them directly from <img> or <Image> tags.

Endpoints

ResourceURL pattern
Team logohttps://api.mrdoge.co/images/teams/<teamId>.png
Region flaghttps://api.mrdoge.co/images/regions/<regionId>.png

Both return 200 OK with Content-Type: image/png when the image exists.

Caching

Every response sets:

Cache-Control: public, max-age=31536000, immutable

That's one year, immutable: safe to cache aggressively on CDNs, service workers, and browser caches. The IDs are stable identifiers, so an update to a team's logo will only land when a new image is uploaded server-side (which happens infrequently and is treated as a new asset).

Use with the SDK

The Team and Region shapes returned by the SDK don't include the image URL directly, so construct it from the id:

import { MrDoge } from "@mrdoge/node";

const mrdoge = new MrDoge({ apiKey: process.env.MRDOGE_API_KEY! });

const teams = await mrdoge.teams.list({ sports: ["soccer"], limit: 20 });

for (const team of teams) {
  console.log(`https://api.mrdoge.co/images/teams/${team.id}.png`);
}

A small helper keeps it tidy:

export function teamLogo(id: number) {
  return `https://api.mrdoge.co/images/teams/${id}.png`;
}

export function regionFlag(id: number) {
  return `https://api.mrdoge.co/images/regions/${id}.png`;
}

In your app

<img
  src={`https://api.mrdoge.co/images/teams/${team.id}.png`}
  alt={team.name}
  width={32}
  height={32}
/>

Plain <img> tags work everywhere. The 1-year cache header means subsequent loads come from the browser cache.

Missing images

Not every team or region has a logo in the catalog. If the image is missing, the endpoint returns a non-200 status. Handle it with a fallback:

<img
  src="https://api.mrdoge.co/images/teams/14.png"
  alt="Liverpool"
  onerror="this.src='/fallback-team.png'"
/>

A colored circle with the team's initials is a common fallback: works without needing a generic asset:

function TeamLogo({ team }: { team: { id: number; name: string } }) {
  const [failed, setFailed] = useState(false);

  if (failed) {
    return (
      <div className="initials-circle">
        {team.name.split(" ").map((w) => w[0]).join("").slice(0, 2)}
      </div>
    );
  }

  return (
    <img
      src={`https://api.mrdoge.co/images/teams/${team.id}.png`}
      alt={team.name}
      onError={() => setFailed(true)}
    />
  );
}

What you don't get

  • No on-the-fly resizing. The endpoint serves the source PNG as-is. For responsive sizes, run images through your own optimizer (next/image, Cloudflare Images, imgix, etc.).
  • No format negotiation. PNG only. Use your image-optimization layer to convert to WebP/AVIF.
  • No competition logos. Only teams and regions have image endpoints. For competition branding, use the region's flag or the home team's logo as a contextual fallback.
  • No player headshots. Player references inside MatchStats are name-only, no per-player imagery.

Performance notes

  • CDN-cached. Cached at the edge in front of api.mrdoge.co and at the browser/SW layer. Cold-fetch is a single round-trip; subsequent loads come from cache.
  • No auth round-trip. The endpoint is excluded from API-key auth middleware. No Authorization header required.
  • Concurrent dedup. When many UI cards mount simultaneously and request the same URL, both browsers and expo-image dedupe to a single fetch.

Next

On this page