Skip to main content

> Exitability Oracle API

REST API for querying memecoin exitability on Solana. Base URL: https://app.memedetector.es

All responses are JSON. All timestamps are UTC ISO-8601.

Authentication

The API uses API keys for authenticated access. Pass your key in the x-api-key HTTP header:

curl -H "x-api-key: mdo_your_api_key_here" \
  https://app.memedetector.es/api/token/{id}/exitability

How to get an API key

  1. Call POST /api/oracle/register with your email
  2. Receive an mdo_* API key in the response
  3. Include it as x-api-key in all subsequent requests

Anonymous requests (no API key) are allowed but limited to 5 queries/day per IP.

Exitability Query

GET/api/token/{id}/exitability

Returns the exitability assessment for a Solana token. This is the core endpoint: it tells you whether you can exit a position at a given size, and at what slippage.

Path Parameters

ParameterTypeRequiredDescription
idstringrequiredToken mint address (Solana base58)

Query Parameters

ParameterTypeRequiredDescription
profilestringoptionalUser profile: "retail" (default) or "pro"
sizenumberoptionalPosition size in SOL (default: 1). Snaps to nearest available: 0.5, 1, 2, 5, 10, 50

Headers

ParameterTypeRequiredDescription
x-api-keystringoptionalYour API key (mdo_*). Omit for anonymous access (5/day limit)

Example Request

curl "https://app.memedetector.es/api/token/EHANMoxJnqqS4TBCka7amq9EBhWuMgZuRQfheqjwpump/exitability?profile=retail&size=2"

Example Response (200)

{
  "state": "ok",
  "token_id": "EHANMoxJnqqS4TBCka7amq9EBhWuMgZuRQfheqjwpump",
  "fase": "on-curve",
  "amm": "pumpswap",
  "calidad_dato": "suficiente",
  "confianza": "media",
  "aviso": null,
  "depth_sol": 85.3,
  "precio_mid": 4.2e-7,
  "score": 74,
  "exit_max_sol": 12.5,
  "slippage": {
    "size_requested": 2,
    "size_used": 2,
    "slip_pct": 3.45,
    "all": {
      "1": 1.72,
      "2": 3.45,
      "5": 8.61,
      "10": 17.2,
      "50": null,
      "0.5": 0.87
    }
  },
  "trend": "stable",
  "alerta_deterioro": false,
  "updated_at": "2026-06-10T14:30:00.000Z",
  "profile": "retail"
}

Response Fields

FieldTypeDescription
statestring"ok", "bloqueado_dato", "bloqueado_tamano_amm", or "not_found"
token_idstringMint address
fasestringToken lifecycle phase: "on-curve", "migrated", etc.
ammstringAMM detected: "pumpswap", "raydium", "meteora", "otro"
calidad_datostringData quality: "suficiente" or "insuficiente"
confianzastringConfidence level: "alta", "media", "baja"
avisostring|nullWarning message if confidence was downgraded
depth_solnumberTotal liquidity depth in SOL
precio_midnumberMid price in SOL
scorenumberExitability score (0-100). Higher = easier to exit
exit_max_solnumberMax recommended exit size in SOL
slippageobjectSlippage data (see below)
slippage.size_requestednumberThe size you requested
slippage.size_usednumberNearest available size used for calculation
slippage.slip_pctnumber|nullEstimated slippage in % for the requested size
slippage.allobjectSlippage % for all standard sizes (0.5, 1, 2, 5, 10, 50)
trendstringLiquidity trend: "improving", "stable", or "deteriorating"
alerta_deteriorobooleanTrue if rapid liquidity deterioration detected
updated_atstringISO-8601 timestamp of last data update
profilestringThe profile used for the query

Blocked States

bloqueado_dato -- Insufficient data quality. The depth reconstruction is unreliable for this token.

bloqueado_tamano_amm -- AMM is unidentified and requested size exceeds 10 SOL. Max allowed: 10 SOL for unknown AMMs.

not_found -- No exitability data exists for this token.

Register

POST/api/oracle/register

Register a free account and receive an API key. If the email is already registered, returns the existing key.

Request Body (JSON)

ParameterTypeRequiredDescription
emailstringrequiredValid email address

Example Request

curl -X POST https://app.memedetector.es/api/oracle/register \
  -H "Content-Type: application/json" \
  -d '{"email": "you@example.com"}'

Example Response (201)

{
  "status": "registered",
  "api_key": "mdo_a1b2c3d4e5f6...",
  "tier": "free",
  "daily_limit": 10,
  "message": "Registered. Use this API key in the x-api-key header for 10 queries/day.",
  "usage": "curl -H 'x-api-key: YOUR_KEY' https://app.memedetector.es/api/token/{id}/exitability"
}

Already Registered (200)

{
  "status": "already_registered",
  "api_key": "mdo_a1b2c3d4e5f6...",
  "tier": "free",
  "daily_limit": 10,
  "message": "Already registered. Use this API key in the x-api-key header."
}

Waitlist

POST/api/oracle/waitlist

Join the waitlist for paid tiers (Degen / Founder). Each submission is an intent signal.

Request Body (JSON)

ParameterTypeRequiredDescription
emailstringrequiredValid email address
origenstringoptionalReferral source (default: "api")

Example Request

curl -X POST https://app.memedetector.es/api/oracle/waitlist \
  -H "Content-Type: application/json" \
  -d '{"email": "you@example.com", "origen": "api-docs"}'

Example Response (201)

{
  "status": "waitlisted",
  "message": "Added to the Degen Access waitlist (19 EUR/month). We will notify you when spots open."
}

Events

POST/api/oracle/event

Track a GTM event. Used for analytics and funnel tracking.

Request Body (JSON)

ParameterTypeRequiredDescription
event_namestringrequiredOne of the valid event names (see below)
emailstringoptionalUser email if available
payloadobjectoptionalArbitrary JSON payload for context
utm_sourcestringoptionalUTM source tag
utm_mediumstringoptionalUTM medium tag
utm_campaignstringoptionalUTM campaign tag

Valid Event Names

registrowaitlist_emailclick_pagarcheckout_iniciadopago_realclick_upgrade_desde_limiteclick_avisame_proalerta_clickwatchlist_add

Example Request

curl -X POST https://app.memedetector.es/api/oracle/event \
  -H "Content-Type: application/json" \
  -d '{"event_name": "registro", "email": "you@example.com"}'

Example Response (201)

{
  "status": "recorded",
  "event_name": "registro"
}

Watchlist

Watchlist endpoints require session authentication (Supabase auth cookie or Bearer token). These are designed for the dashboard frontend, not for direct API key usage.

GET/api/oracle/watchlist

Returns the authenticated user's watchlist with enriched exitability data for each token.

Headers

ParameterTypeRequiredDescription
AuthorizationstringrequiredBearer <supabase_access_token>

Example Response (200)

{
  "items": [
    {
      "id": 42,
      "user_id": "uuid",
      "mint": "EHANMoxJnqqS4TBCka7amq9EBhWuMgZuRQfheqjwpump",
      "size_sol": 2,
      "alerts_enabled": true,
      "created_at": "2026-06-10T10:00:00.000Z",
      "exitability": {
        "state": "ok",
        "score": 74,
        "depth_sol": 85.3,
        "exit_max_sol": 12.5,
        "slippage_pct": 3.45,
        "trend": "stable",
        "alerta_deterioro": false,
        "confianza": "media",
        "calidad_dato": "suficiente",
        "updated_at": "2026-06-10T14:30:00.000Z",
        "token_name": "Example Token",
        "token_symbol": "EXT"
      }
    }
  ]
}
POST/api/oracle/watchlist

Add a token to the watchlist. Free plan: 1 token. Pro: 10 tokens.

Request Body (JSON)

ParameterTypeRequiredDescription
mintstringrequiredToken mint address (min 10 chars)
size_solnumberoptionalPosition size in SOL for alerts (default: 1, range: 0.01-1000)

Example Response (201)

{
  "status": "added",
  "id": 42
}
DELETE/api/oracle/watchlist?id={id}

Remove a token from the watchlist.

Query Parameters

ParameterTypeRequiredDescription
idnumberrequiredWatchlist entry ID

Example Response (200)

{
  "status": "deleted"
}
PATCH/api/oracle/watchlist

Update watchlist entry (size or alerts).

Request Body (JSON)

ParameterTypeRequiredDescription
idnumberrequiredWatchlist entry ID
size_solnumberoptionalNew position size in SOL (0.01-1000)
alerts_enabledbooleanoptionalEnable/disable deterioration alerts

Example Response (200)

{
  "status": "updated"
}

Rate Limits

Rate limits are enforced per day (UTC midnight reset). The response headers X-RateLimit-Limit and X-RateLimit-Remaining are included in every exitability response.

TierDaily LimitWatchlistPriceHow to Get
Anonymous5 / day--FreeNo API key needed
Free10 / day1 tokenFreePOST /api/oracle/register
DegenUnlimited10 tokens19 EUR / monthWaitlist (coming soon)
FounderUnlimitedUnlimitedBy invitationContact info@memedetector.es

429 Too Many Requests

When you exceed your daily limit, the API returns 429 with a Retry-After: 86400 header and a JSON body:

{
  "error": "rate_limit_exceeded",
  "message": "Daily limit reached (10 queries/day).",
  "used": 10,
  "limit": 10,
  "register_url": null,
  "waitlist_url": "/api/oracle/waitlist",
  "upgrade_cta": "Degen Access 19 EUR/month -- join the waitlist"
}

B2B Use Cases

Exitability Badge in a Telegram Bot

Show users whether they can exit a token before they ape in. Query the exitability endpoint when a user sends a mint address, and display the score + slippage as a compact badge.

# Python example: Telegram bot handler
import requests

def check_exit(mint: str, size: float = 1) -> str:
    r = requests.get(
        f"https://app.memedetector.es/api/token/{mint}/exitability",
        params={"size": size},
        headers={"x-api-key": "mdo_your_key"},
    )
    d = r.json()
    if d.get("state") != "ok":
        return f"No data for {mint[:8]}..."
    score = d["score"]
    slip = d["slippage"]["slip_pct"]
    trend = d["trend"]
    return (
        f"EXIT SCORE: {score}/100 | "
        f"Slippage at {size} SOL: {slip}% | "
        f"Trend: {trend}"
    )

Deterioration Alert in a Trading Terminal

Poll the exitability endpoint periodically for tokens in your portfolio. When alerta_deterioro flips to true or trend changes to "deteriorating", trigger an alert to the trader.

# Cron job: check deterioration every 30 minutes
MINTS=("EHANMoxJnqqS4TBCka7amq9EBhWuMgZuRQfheqjwpump" "AnotherMintHere...")
for mint in "${MINTS[@]}"; do
  resp=$(curl -s -H "x-api-key: mdo_your_key" \
    "https://app.memedetector.es/api/token/${mint}/exitability?size=5")
  deterioro=$(echo "$resp" | jq -r '.alerta_deterioro')
  if [ "$deterioro" = "true" ]; then
    echo "ALERT: $mint liquidity deteriorating"
    # Send notification via webhook, Telegram, etc.
  fi
done

Embeddable Widget

Build a lightweight widget that fetches exitability data and renders a visual indicator. Ideal for portfolio trackers, token pages, or community dashboards.

// React component example
async function ExitBadge({ mint, size = 1 }) {
  const res = await fetch(
    `https://app.memedetector.es/api/token/${mint}/exitability?size=${size}`,
    { headers: { "x-api-key": "mdo_your_key" } }
  );
  const data = await res.json();
  if (data.state !== "ok") return <span>N/A</span>;

  const color = data.score >= 70 ? "green"
    : data.score >= 40 ? "yellow" : "red";

  return (
    <div style={{ borderLeft: `3px solid ${color}`, padding: "8px" }}>
      <strong>Exit Score: {data.score}/100</strong>
      <br />
      Slippage at {size} SOL: {data.slippage.slip_pct}%
      {data.alerta_deterioro && <span> -- DETERIORATING</span>}
    </div>
  );
}

Error Reference

HTTPerrorMeaning
400invalid_bodyRequest body is not valid JSON
400invalid_emailEmail format is invalid
400missing_event_nameevent_name field is required
400invalid_event_nameevent_name is not in the allowed list
400invalid_mintMint address too short (min 10 chars)
400invalid_sizesize_sol out of range (0.01-1000)
400no_changesPATCH body has no updateable fields
401unauthorizedSession not valid (watchlist endpoints)
403limit_reachedWatchlist token limit reached for your plan
404not_foundNo exitability data for this token
409duplicateToken already in your watchlist
429rate_limit_exceededDaily query limit reached. Retry after UTC midnight.
500server_errorInternal server error. Contact support.

Need help? Contact us at info@memedetector.es or join our Telegram.