Skip to main content

Exit-Safety API

REST API for measuring observed exitability conditions on Solana. Base URL: https://app.memedetector.es

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

Measurements only. Exit-Safety API does not execute transactions, recommend trades, predict prices or identify a best time to buy or sell.

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 safely

  1. Create an account and sign in at app.memedetector.es
  2. Open the dashboard's Exit-Safety API page and activate access
  3. Copy the session-protected key and 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.

The public registration endpoint never returns an API key and never reveals whether an email was already registered.

Exit-Safety Query

GET/api/token/{id}/exitability

Returns an observed exitability measurement for a Solana token. It reports modeled slippage and liquidity conditions for a requested size; it does not determine what action a user should take.

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_solnumberLargest standard size modeled below the 10% slippage threshold
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

Requests creation of a free account. The response is deliberately identical whether the email was new or already registered and never contains an API 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 (200)

{
  "status": "registered",
  "message": "If this email was not registered, an account has been created. Sign in to view your API key."
}

Retrieve the key only after authentication from the Exit-Safety API page in the dashboard. Never place a key in browser code.

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
DegenNot counted by the current daily gate*20 tokensSee current plansAccount billing
FounderNot counted by the current daily gate*50 tokensSee current plansAccount billing
ProNot counted by the current daily gate*100 tokensSee current plansAccount billing

* Paid tiers remain subject to fair-use, abuse prevention and infrastructure safeguards even when the daily counter is bypassed.

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

Query a mint and display the observed Exit Score, modeled slippage and data confidence as a compact measurement. The badge should not be presented as a buy or sell signal.

# 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", flag the position for human review.

# 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>;

  return (
    <div style={{ padding: "8px" }}>
      <strong>Exit Score: {data.score}/100</strong>
      <br />
      Slippage at {size} SOL: {data.slippage.slip_pct}%
      {data.alerta_deterioro && <span> -- DETERIORATING</span>}
      <small>Measurement only — not trading advice.</small>
    </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.

EXIT SQUEEZE by MemeDetector© 2026