MadeOnSol Exports API

Bulk Parquet exports of every fully archived closed month (token_trades, rhc_trades, token_ohlc_1m, rhc_ohlc_1m) via presigned S3 links. BUSINESS+. 1 operation(s) of the keyed MadeOnSol API (Bearer msk_ key).

Operations 1

GET /exports Bulk Parquet exports of archived months (BUSINESS+) #

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/madeonsol:madeonsol-exports-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

madeonsol-exports-api-openapi.yml Raw ↑
openapi: 3.2.0
info:
  title: MadeOnSol Exports API
  version: 1.20.0
  description: Real-time Solana & Robinhood Chain trading intelligence — KOL wallet trades, deployer reputation, token buyer-quality scoring, wallet tracking, and copy-trade signals across both chains (Robinhood Chain paths under `/rhc/*`).
  contact:
    name: MadeOnSol
    url: https://madeonsol.com/contact
  license:
    name: Proprietary
    url: https://madeonsol.com/terms
servers:
- url: https://madeonsol.com/api/v1
  description: Production
security:
- BearerAuth: []
tags:
- name: Exports
  description: Bulk Parquet exports of every fully archived closed month (token_trades, rhc_trades, token_ohlc_1m, rhc_ohlc_1m) via presigned S3 links. BUSINESS+.
paths:
  /exports:
    get:
      tags:
      - Exports
      summary: Bulk Parquet exports of archived months (BUSINESS+)
      description: 'BUSINESS+ (BASIC/PRO/ULTRA get 403 with an `upgrade` block; ENTERPRISE passes). Two modes on one route.


        **Listing** (no params): every fully archived closed month per dataset — `token_trades`, `rhc_trades`, `token_ohlc_1m`, `rhc_ohlc_1m` — with row count, byte size and file count. A month appears only once both archive providers have verified it (the same ledger the nightly archive exporter writes), so the list is the set you can actually download.


        **Download** (`dataset` + `month`): presigned S3 GET links for that month''s Parquet files (zstd-compressed, one or more files per month). Links are valid for about **1 hour** — fetch them when you are ready to download, not ahead of time; re-request to mint fresh ones. The ledger row count is returned so you can verify the files you pulled. Both params are required together.


        The current (open) month is never listed — it is live in Postgres and served by the paginated endpoints (`/tokens/{mint}/trades`, `/rhc/trades`, `/tokens/{mint}/candles`). Files are identical to the immutable dual-provider archive described at https://madeonsol.com/data-integrity — ideal for backtests, model training and offline analytics without paging through the API.'
      parameters:
      - name: dataset
        in: query
        required: false
        schema:
          type: string
          enum:
          - token_trades
          - rhc_trades
          - token_ohlc_1m
          - rhc_ohlc_1m
        description: Dataset to download. Required together with `month`; omit both to list.
      - name: month
        in: query
        required: false
        schema:
          type: string
          pattern: ^\d{4}-\d{2}$
          example: 2026-07
        description: Closed month `YYYY-MM` (UTC). Required together with `dataset`.
      responses:
        '200':
          description: Listing (no params) or one month's download links (dataset + month).
          content:
            application/json:
              schema:
                oneOf:
                - type: object
                  title: ExportListing
                  required:
                  - datasets
                  properties:
                    datasets:
                      type: array
                      items:
                        type: object
                        required:
                        - dataset
                        - months
                        properties:
                          dataset:
                            type: string
                            enum:
                            - token_trades
                            - rhc_trades
                            - token_ohlc_1m
                            - rhc_ohlc_1m
                          months:
                            type: array
                            description: Fully archived closed months, newest first.
                            items:
                              type: object
                              required:
                              - month
                              - rows
                              - bytes
                              - files
                              properties:
                                month:
                                  type: string
                                  example: 2026-07
                                  description: '`YYYY-MM`, UTC-derived closed month'
                                rows:
                                  type: integer
                                  description: Row count recorded in the archive ledger at export time
                                bytes:
                                  type: integer
                                  description: Total compressed Parquet bytes for the month
                                files:
                                  type: integer
                                  description: Number of Parquet files the month is split into
                - type: object
                  title: ExportMonth
                  required:
                  - dataset
                  - month
                  - rows
                  - bytes
                  - files
                  - license_note
                  properties:
                    dataset:
                      type: string
                      enum:
                      - token_trades
                      - rhc_trades
                      - token_ohlc_1m
                      - rhc_ohlc_1m
                    month:
                      type: string
                      example: 2026-07
                    rows:
                      type: integer
                    bytes:
                      type: integer
                    files:
                      type: array
                      items:
                        type: object
                        required:
                        - name
                        - bytes
                        - url
                        - expires_at
                        properties:
                          name:
                            type: string
                            description: Object name, e.g. `token_trades/2026-07/part-0001.parquet`
                          bytes:
                            type: integer
                          url:
                            type: string
                            format: uri
                            description: Presigned S3 GET URL — no auth header needed, plain HTTP GET
                          expires_at:
                            type: string
                            format: date-time
                            description: When the presigned URL stops working (~1 h after issue)
                    license_note:
                      type: string
                      description: The terms the files are released under (BUSINESS embed license; redistribution is ENTERPRISE)
          headers:
            X-Request-Id:
              $ref: '#/components/headers/XRequestId'
            X-RateLimit-Limit:
              $ref: '#/components/headers/XRateLimitLimit'
            X-RateLimit-Remaining:
              $ref: '#/components/headers/XRateLimitRemaining'
            X-RateLimit-Used:
              $ref: '#/components/headers/XRateLimitUsed'
            X-RateLimit-Reset:
              $ref: '#/components/headers/XRateLimitReset'
            X-Data-Delay:
              $ref: '#/components/headers/XDataDelay'
            X-MadeOnSol-Quota-Warning:
              $ref: '#/components/headers/XMadeOnSolQuotaWarning'
        '400':
          description: '`dataset` or `month` invalid, or only one of the two given.'
          content:
            application/json:
              schema:
                type: object
                required:
                - error
                properties:
                  error:
                    type: string
                    enum:
                    - invalid_params
          headers:
            X-Request-Id:
              $ref: '#/components/headers/XRequestId'
            X-RateLimit-Limit:
              $ref: '#/components/headers/XRateLimitLimit'
            X-RateLimit-Remaining:
              $ref: '#/components/headers/XRateLimitRemaining'
            X-RateLimit-Used:
              $ref: '#/components/headers/XRateLimitUsed'
            X-RateLimit-Reset:
              $ref: '#/components/headers/XRateLimitReset'
        '401':
          $ref: '#/components/responses/Unauthorized'
        '403':
          description: Tier below BUSINESS. Standard tier-gate body with an `upgrade` block.
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/Error'
          headers:
            X-Request-Id:
              $ref: '#/components/headers/XRequestId'
            X-RateLimit-Limit:
              $ref: '#/components/headers/XRateLimitLimit'
            X-RateLimit-Remaining:
              $ref: '#/components/headers/XRateLimitRemaining'
            X-RateLimit-Used:
              $ref: '#/components/headers/XRateLimitUsed'
            X-RateLimit-Reset:
              $ref: '#/components/headers/XRateLimitReset'
        '404':
          description: That month is not (yet) fully archived for that dataset — it is either the open month or still being verified.
          content:
            application/json:
              schema:
                type: object
                required:
                - error
                properties:
                  error:
                    type: string
                    enum:
                    - month_not_archived
          headers:
            X-Request-Id:
              $ref: '#/components/headers/XRequestId'
            X-RateLimit-Limit:
              $ref: '#/components/headers/XRateLimitLimit'
            X-RateLimit-Remaining:
              $ref: '#/components/headers/XRateLimitRemaining'
            X-RateLimit-Used:
              $ref: '#/components/headers/XRateLimitUsed'
            X-RateLimit-Reset:
              $ref: '#/components/headers/XRateLimitReset'
        '429':
          $ref: '#/components/responses/RateLimited'
        '500':
          $ref: '#/components/responses/InternalError'
        '502':
          description: The archive store could not be reached to sign the links. Retry later; nothing was consumed from your quota.
          content:
            application/json:
              schema:
                type: object
                required:
                - error
                properties:
                  error:
                    type: string
                    enum:
                    - archive_unavailable
          headers:
            X-Request-Id:
              $ref: '#/components/headers/XRequestId'
            X-RateLimit-Limit:
              $ref: '#/components/headers/XRateLimitLimit'
            X-RateLimit-Remaining:
              $ref: '#/components/headers/XRateLimitRemaining'
            X-RateLimit-Used:
              $ref: '#/components/headers/XRateLimitUsed'
            X-RateLimit-Reset:
              $ref: '#/components/headers/XRateLimitReset'
        '503':
          $ref: '#/components/responses/AuthBackendUnavailable'
      x-madeonsol-tier: BUSINESS
      x-badges:
      - name: BUSINESS
        position: after
        color: '#7c3aed'
      operationId: getExports
      x-operation-id-source: derived
components:
  schemas:
    ServiceUnavailableError:
      type: object
      description: '503: a temporary capacity or maintenance condition (e.g. a Postgres statement timeout during a partition move, or the API-key lookup itself being unavailable). Retry after `Retry-After` seconds.'
      required:
      - error
      properties:
        error:
          type: string
        code:
          type: string
          description: Machine-readable code where one exists, e.g. `auth_backend_unavailable`.
        error_kind:
          type: string
          description: e.g. `statement_timeout`, `auth_backend`
        retry_after_seconds:
          type: number
        retryable:
          type: boolean
        support:
          type: string
        _rid:
          type: string
    RateLimitError:
      type: object
      description: '429 when a quota is exhausted: the daily quota, the per-minute burst, or a free-tier network/key-rotation cap. `datasets` is added on `daily` only.'
      required:
      - error
      - error_kind
      - message
      - tier
      - limit
      - resets_at
      properties:
        error:
          type: string
          enum:
          - rate_limit_exceeded
        error_kind:
          type: string
          enum:
          - daily
          - burst
          - ip_cap
          - ip_rotation
        message:
          type: string
        tier:
          type: string
          enum:
          - BASIC
          - PRO
          - ULTRA
          - BUSINESS
          - ENTERPRISE
        limit:
          type: integer
        resets_at:
          type: string
          format: date-time
        upgrade:
          type: object
          description: The plan that lifts this limit, with price and a checkout link.
          properties:
            tier:
              type: string
              enum:
              - PRO
              - ULTRA
              - BUSINESS
              - ENTERPRISE
            price_eur_per_month:
              type: number
            price_usdc_per_month:
              type: number
            daily_limit:
              type: integer
            burst_limit:
              type: integer
            pitch:
              type: string
            url:
              type: string
            upgrade_url:
              type: string
              format: uri
            reactivate:
              type: boolean
              description: Present (true) when the key's paid subscription has just lapsed and `tier` is the plan it held.
            prior_tier:
              type: string
              enum:
              - PRO
              - ULTRA
              - BUSINESS
        datasets:
          type: object
          properties:
            pitch:
              type: string
            url:
              type: string
              format: uri
    ConcurrencyLimitError:
      type: object
      description: '429 from the heavy-query limiter: too many heavy requests in flight for this key (`concurrency`) or for the whole server (`capacity`). Clears as soon as in-flight requests finish.'
      required:
      - error
      - error_kind
      - retry_after_seconds
      properties:
        error:
          type: string
        error_kind:
          type: string
          enum:
          - concurrency
          - capacity
        retry_after_seconds:
          type: number
        max_concurrent:
          type: integer
        support:
          type: string
        _rid:
          type: string
    Error:
      type: object
      description: Generic error envelope. `error` is always present (SDKs match on it). Errors returned after authentication also carry `_rid` and, on paid tiers, `support`; authentication-stage errors (missing/invalid key, origin) carry neither.
      properties:
        error:
          type: string
          description: Error message or machine code (e.g. `tier_required`, `rate_limit_exceeded`). Never changed once shipped.
        message:
          type: string
          description: Human-readable explanation, when `error` is a machine code.
        code:
          type: string
          description: Machine-readable sub-code on some errors (e.g. `invalid_query`, `invalid_wallet`, `origin_not_allowed`).
        error_kind:
          type: string
          description: Machine-readable category on some errors (e.g. `statement_timeout`, `concurrency`, `daily`).
        detail:
          type: string
          description: Extra human-readable context.
        hint:
          type: string
        retry_after_seconds:
          type: number
          description: When present on a 429/503, the same value is sent as the `Retry-After` header.
        signup_url:
          type: string
          format: uri
          description: 'On the missing-key / bad-format 401: where to get a free key.'
        docs_url:
          type: string
          format: uri
        support:
          type: string
          description: 'Paid tiers, errors after authentication: priority support contact.'
        _rid:
          type: string
          description: Request ID — include when reporting issues
      required:
      - error
  headers:
    XRateLimitReset:
      description: When the window resets, as a Unix epoch in SECONDS (next 00:00 UTC for the daily quota; about 60 s ahead for a per-minute bucket).
      schema:
        type: integer
      example: 1791158400
    XRateLimitRemaining:
      description: Calls left in that window. `0` on a quota 429.
      schema:
        type: integer
        minimum: 0
      example: 9412
    XMadeOnSolQuotaWarning:
      description: 'Free-tier only, past about 70 % of the daily quota: a human-readable usage line with an upgrade link.'
      schema:
        type: string
      example: '150/200 used - upgrade for 50x higher limits: https://madeonsol.com/checkout?tier=PRO'
    XRateLimitUsed:
      description: Calls used in that window (`limit − remaining`).
      schema:
        type: integer
        minimum: 0
      example: 588
    RetryAfter:
      description: Seconds to wait before retrying (RFC 9110 delay-seconds, at least 1). Sent on every 429 (quota, concurrency, authentication-failure) and every 503; when the body carries `retry_after_seconds` it is the same value.
      required: true
      schema:
        type: integer
        minimum: 1
      example: 10
    XDataDelay:
      description: 'Free-tier only: the feed in this body is delayed by this many seconds (same value as the body''s `delay_seconds`). Absent on real-time responses.'
      schema:
        type: integer
        minimum: 1
      example: 300
    XRateLimitLimit:
      description: 'Size of the rate-limit window this call was counted against: the daily quota for your tier on data endpoints, the per-minute bucket on `/stream/token` (10) and `/stream/sessions` (30), the hourly allowance for the public demo key. Sent once the key has been authenticated and rate-limited, so it is absent on authentication-stage errors.'
      schema:
        type: integer
        minimum: 0
      example: 10000
    XRequestId:
      description: Unique id of this response. On responses built after authentication it is also the `request_id` of the audit-log row for the call, so quote it in a support request. Present on every response of the keyed API.
      required: true
      schema:
        type: string
        format: uuid
      example: 3f6c1d2e-8a4b-4f7e-9c21-5b0d7e6a9f13
  responses:
    AuthBackendUnavailable:
      description: 'The API-key or subscription lookup could not be answered (authentication stage). Retryable and not your fault: it is never counted as a failed authentication. Honour `Retry-After`; no `X-RateLimit-*`, no `_rid`.'
      headers:
        X-Request-Id:
          $ref: '#/components/headers/XRequestId'
        Retry-After:
          $ref: '#/components/headers/RetryAfter'
      content:
        application/json:
          schema:
            $ref: '#/components/schemas/ServiceUnavailableError'
          examples:
            auth_backend:
              summary: API-key lookup unavailable
              value:
                error: Authentication temporarily unavailable — please retry.
                code: auth_backend_unavailable
                error_kind: auth_backend
                retryable: true
                retry_after_seconds: 5
    InternalError:
      description: Unexpected server error from the route (`Internal server error`, with `_rid`). Safe to retry with backoff. A failed API-key lookup is a 503 `auth_backend_unavailable`, never a 500.
      headers:
        X-Request-Id:
          $ref: '#/components/headers/XRequestId'
        X-RateLimit-Limit:
          $ref: '#/components/headers/XRateLimitLimit'
        X-RateLimit-Remaining:
          $ref: '#/components/headers/XRateLimitRemaining'
        X-RateLimit-Used:
          $ref: '#/components/headers/XRateLimitUsed'
        X-RateLimit-Reset:
          $ref: '#/components/headers/XRateLimitReset'
      content:
        application/json:
          schema:
            $ref: '#/components/schemas/Error'
          examples:
            route:
              summary: Route error
              value:
                error: Internal server error
                _rid: eyJ1IjoiZXhhbXBsZSIsInQiOjE3OTEwMDAwMDAwMDAsImgiOiIwMDAwMDAwMCJ9
    Unauthorized:
      description: 'Missing or invalid API key, or an expired free-tier key. Authentication-stage error: no `X-RateLimit-*` headers, no `_rid`.'
      headers:
        X-Request-Id:
          $ref: '#/components/headers/XRequestId'
      content:
        application/json:
          schema:
            $ref: '#/components/schemas/Error'
          examples:
            missing_key:
              summary: No Bearer key
              value:
                error: 'Missing authentication — use API key (Authorization: Bearer msk_...)'
                hint: Get a free API key — 200 calls/day, no payment
                signup_url: https://madeonsol.com/developer
                docs_url: https://madeonsol.com/api-docs
            bad_format:
              summary: Malformed key
              value:
                error: Invalid API key format
                hint: Get a free API key — 200 calls/day, no payment
                signup_url: https://madeonsol.com/developer
                docs_url: https://madeonsol.com/api-docs
    RateLimited:
      description: Too many requests. Every 429 carries `Retry-After`. A quota 429 (`rate_limit_exceeded`, with `X-RateLimit-*`), a heavy-query concurrency 429 (`error_kind` `concurrency`/`capacity`), or the per-IP authentication-failure block (30 failed auths/min; plain `error` + `retry_after_seconds`, no `X-RateLimit-*`).
      headers:
        X-Request-Id:
          $ref: '#/components/headers/XRequestId'
        X-RateLimit-Limit:
          $ref: '#/components/headers/XRateLimitLimit'
        X-RateLimit-Remaining:
          $ref: '#/components/headers/XRateLimitRemaining'
        X-RateLimit-Used:
          $ref: '#/components/headers/XRateLimitUsed'
        X-RateLimit-Reset:
          $ref: '#/components/headers/XRateLimitReset'
        Retry-After:
          $ref: '#/components/headers/RetryAfter'
      content:
        application/json:
          schema:
            anyOf:
            - $ref: '#/components/schemas/RateLimitError'
            - $ref: '#/components/schemas/ConcurrencyLimitError'
            - $ref: '#/components/schemas/Error'
          examples:
            daily:
              summary: Daily quota exhausted
              value:
                error: rate_limit_exceeded
                error_kind: daily
                message: Daily rate limit exceeded — 200/day for BASIC tier. Resets at midnight UTC.
                tier: BASIC
                limit: 200
                resets_at: '2026-10-05T00:00:00.000Z'
                upgrade:
                  tier: PRO
                  price_eur_per_month: 43
                  price_usdc_per_month: 49
                  daily_limit: 10000
                  burst_limit: 300
                  pitch: …
                  url: https://madeonsol.com/pricing
                  upgrade_url: https://madeonsol.com/checkout?tier=PRO
                datasets:
                  pitch: …
                  url: https://madeonsol.com/datasets
            concurrency:
              summary: Too many heavy queries in flight
              value:
                error: Too many concurrent heavy queries. Up to 8 of these endpoints may be in flight at once per key — retry in a moment, or lower your request concurrency.
                error_kind: concurrency
                retry_after_seconds: 2
                max_concurrent: 8
                _rid: eyJ1IjoiZXhhbXBsZSIsInQiOjE3OTEwMDAwMDAwMDAsImgiOiIwMDAwMDAwMCJ9
            auth_failures:
              summary: Per-IP authentication-failure block
              value:
                error: Too many authentication failures from this IP. Retry in 60s.
                retry_after_seconds: 42
  securitySchemes:
    BearerAuth:
      type: http
      scheme: bearer
      bearerFormat: msk_...
      description: Get a free API key at https://madeonsol.com/developer
x-madeonsol-tiers:
- tier: FREE
  plan: BASIC
  name: Free
  price_eur_monthly: 0
  price_eur_annual: 0
  price_usd_monthly: 0
  daily_limit: 200
  burst_limit: 60
  url: https://madeonsol.com/developer
- tier: PRO
  plan: PRO
  name: Pro
  price_eur_monthly: 43
  price_eur_annual: 430
  price_usd_monthly: 49
  daily_limit: 10000
  burst_limit: 300
  url: https://madeonsol.com/checkout?tier=PRO
- tier: ULTRA
  plan: ULTRA
  name: Ultra
  price_eur_monthly: 131
  price_eur_annual: 1310
  price_usd_monthly: 149
  daily_limit: 100000
  burst_limit: 600
  url: https://madeonsol.com/checkout?tier=ULTRA
- tier: BUSINESS
  plan: BUSINESS
  name: Business
  price_eur_monthly: 400
  price_eur_annual: 4000
  price_usd_monthly: 456
  daily_limit: 500000
  burst_limit: 3000
  url: https://madeonsol.com/checkout?tier=BUSINESS
- tier: ENTERPRISE
  plan: ENTERPRISE
  name: Enterprise
  price_eur_monthly: null
  price_eur_annual: null
  price_usd_monthly: null
  daily_limit: null
  burst_limit: null
  url: https://madeonsol.com/pricing#enterprise