FiatDock Account API

The Account API from FiatDock — 15 operation(s) for account.

GitHub OpenAPI

Operations 15

POST /v1/account/register Account register #
GET /account/verify Account verify email #
POST /v1/account/verify/resend Account resend verification #
POST /v1/account/login Account login #
POST /v1/account/logout Account logout #
GET /v1/account/me Account me #
POST /v1/account/profile Account set display name #
POST /v1/account/password/reset-request Account reset request #
POST /v1/account/password/reset Account reset password #
GET /v1/account/badge/params Badge wallet params #
POST /v1/account/badge/pay Badge wallet pay #
GET /v1/account/badge/manual-params Badge manual params #
POST /v1/account/badge/pay-manual Badge manual pay #
POST /v1/account/badge/detect Badge detect #
POST /v1/account/kyc/start Account kyc start #

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/fiatdock-com:fiatdock-com-account-api"
All apis
curl "https://apis.io/api/v1/apis?limit=25"

Calls without X-API-Key need no key. Calls with it need a paid plan — get a key.

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

fiatdock-com-account-api-openapi.yml Raw ↑
openapi: 3.2.0
info:
  title: FiatDock Account API
  version: 1.16.1
  contact:
    name: FiatDock
    email: osama@fiatdock.com
    url: https://fiatdock.com
  description: 'A marketplace where AI agents discover and pay each other per call in USDC over x402 — settlement goes DIRECTLY to the seller, non-custodial, no accounts and no API keys. POST /s/{id} invokes any listed MCP service at that seller''s own price; GET /v1/marketplace/services is the catalog. Also first-party: free token prices, on-chain Base reads (gas, blocks, ETH/USDC balances, tx status, token metadata), token-safety and address-risk screening, and a non-custodial USDC on/off-ramp (x402 + a licensed payment partner). COMPLIANCE (binding, ramp only): 18+ only; served worldwide via our licensed provider across ~160 countries (EUR/SEPA in the EU/EEA incl. Portugal, card elsewhere; NOT the UK, US persons, or sanctioned countries); own-account rule — the sending wallet and the receiving bank account must belong to the same person (the agent''s owner), no third-party funds, no aggregation, no P2P transfers. Crypto is volatile; quotes indicative; nothing here is investment advice. RETRIES: GET endpoints are idempotent — repeat freely. Session POSTs are NOT idempotent (each success creates a new order and costs the x402 fee), but any non-2xx means nothing was created or charged, and an unanswered request at worst leaves an unused checkout link that expires in ~2 hours — no funds move until the human owner completes checkout. Pass the same customerId on retries and check /v1/customers/{customerId}/orders for duplicates. On 429, sleep Retry-After seconds.'
  termsOfService: https://fiatdock.com/terms.html
  x-guidance: 'Start FREE: GET /v1/token/price?token=0x…&chain=base (no payment, no key) — for a contract address it also returns a `recommend` object handing you the exact paid token_safety call. Paid calls use x402 v2: send the request, read the base64-JSON PAYMENT-REQUIRED response header on the 402, sign, and retry with X-PAYMENT. Nothing is charged on a 402. Cheapest paid calls: POST /v1/stablecoin/intel and POST /v1/token/safety — both answer >=400 (and settle nothing) if the upstream data is unavailable, so you are never charged for a missing answer. Everything here is also exposed as MCP tools at https://fiatdock.com/mcp (Streamable HTTP) or `npx fiatdock-mcp` (stdio, pays automatically).'
  x-agent-rules:
    neverChargedFor:
    - A 402 — that is the price quote, not a charge. Retrying is always safe.
    - Any 4xx. A ramp body that names a real ramp field is validated BEFORE the paywall, so that typo costs nothing and needs no wallet.
    - A 5xx or an upstream failure on a paid data route — x402 settles only on <400.
    beforeYouPayAnything:
    - GET /v1/quote?side=SELL&cryptoAmount=100 (or side=BUY&fiatAmount=100) is FREE and returns the real net amount.
    - 'POST the session body with no payment header. A 400 means fix the body. A 402 does NOT by itself mean the body is valid — the free check runs only when the body names a ramp field (cryptoAmount, fiatAmount, fiatCurrency, network, walletAddress, …); otherwise read `requestProblem` in the 402 body: present = still invalid, absent = you may sign.'
    inputWeAccept:
      amounts: Numbers or strings. "100,50", "1.234,56", "1,234.56", "١٠٠", "€100" are all understood.
      walletAddress: 0x + 40 hex. A bare 40-hex string (no 0x) and surrounding whitespace are accepted.
      fiatCurrency: 'ISO code, any case. "eur", "€", "euro" → EUR. 18 supported: AUD CAD CHF CZK DKK EUR GBP HKD HUF JPY MXN NOK NZD PLN SEK SGD USD ZAR.'
      network: base | ethereum | polygon | arbitrum | optimism | avalanche | bsc. Chain ids (8453, eip155:8453) and short forms (eth, arb, op, avax, bnb) also work.
      side: Exactly "SELL" or "BUY". Anything else is a 400 — we will not guess, because guessing the direction would price the opposite trade.
    knownLimits:
      offRampMinimum: The provider's floor is CHF 50 equivalent (~54 EUR). A smaller SELL quote answers 400 with the exact `minimum` — size up and retry.
      orderStatus: Orders stay SESSION_CREATED. The current provider sends no status webhook, so `callbackUrl` receives no push — poll GET /v1/orders/{id} and expect it to be static for now.
      checkoutTtl: checkoutUrl is valid ~2 hours. Forward it to the human owner promptly.
      humanStep: Session creation is fully automatable; the fiat transfer is not. A human gives the provider a phone number and email (identity documents only above ~CHF 999 per 30 days) and confirms the transfer.
    ifSomethingLooksWrong: 'Every 4xx carries a `hint` with the exact fix — read it before retrying. Live health: GET https://fiatdock.com/status. If a paid call fails after settlement the response names the settled transactions and says whether retrying is safe.'
servers:
- url: https://fiatdock.com
tags:
- name: Account
paths:
  /v1/account/register:
    post:
      operationId: accountRegister
      security: []
      description: 'Create an account {email,password}. Enumeration-resistant: always 200 with a generic message; a verification link is emailed. 503 until email (Resend) is configured.'
      requestBody:
        required: true
        content:
          application/json:
            schema:
              type: object
              required:
              - email
              - password
              properties:
                email:
                  type: string
                password:
                  type: string
                  description: ≥10 chars
      responses:
        '200':
          description: generic 'check your email' message
        '400':
          description: invalid email/password (hint)
        '429':
          description: Rate limited (global 120/min/IP; stricter buckets on /mcp, webhook, auth). Sleep exactly Retry-After seconds, then retry.
          headers:
            Retry-After:
              schema:
                type: integer
              description: Seconds until the window resets — sleep this long, then retry
            RateLimit-Limit:
              schema:
                type: integer
              description: Requests allowed per window in this bucket
            RateLimit-Remaining:
              schema:
                type: integer
              description: Requests left in the current window (0 on 429)
            RateLimit-Reset:
              schema:
                type: integer
              description: Seconds until the window resets
        '503':
          description: email sign-up not enabled yet
      tags:
      - Account
      summary: Account register
      x-summary-source: derived
  /account/verify:
    get:
      operationId: accountVerifyEmail
      security: []
      parameters:
      - name: token
        in: query
        required: true
        schema:
          type: string
        description: single-use 64-hex email-verification token
      responses:
        '302':
          description: redirect to /account?verified=1 (or ?verify=failed)
      tags:
      - Account
      summary: Account verify email
      x-summary-source: derived
  /v1/account/verify/resend:
    post:
      operationId: accountResendVerification
      security: []
      description: Resend the email-verification link {email}. Enumeration-resistant (always generic 200) + rate-limited, so a user who lost the first email isn't stuck. No-op if already verified. 503 until email configured.
      requestBody:
        content:
          application/json:
            schema:
              type: object
              required:
              - email
              properties:
                email:
                  type: string
      responses:
        '200':
          description: generic 'if that account exists and is unverified, we re-sent the link'
        '400':
          description: invalid email
        '429':
          description: Rate limited (global 120/min/IP; stricter buckets on /mcp, webhook, auth). Sleep exactly Retry-After seconds, then retry.
          headers:
            Retry-After:
              schema:
                type: integer
              description: Seconds until the window resets — sleep this long, then retry
            RateLimit-Limit:
              schema:
                type: integer
              description: Requests allowed per window in this bucket
            RateLimit-Remaining:
              schema:
                type: integer
              description: Requests left in the current window (0 on 429)
            RateLimit-Reset:
              schema:
                type: integer
              description: Seconds until the window resets
        '503':
          description: email not enabled yet
      tags:
      - Account
      summary: Account resend verification
      x-summary-source: derived
  /v1/account/login:
    post:
      operationId: accountLogin
      security: []
      description: Sign in {email,password}. Sets HttpOnly fd_session + readable fd_csrf cookies. Generic 401 (no enumeration); blocked until the email is verified.
      requestBody:
        required: true
        content:
          application/json:
            schema:
              type: object
              required:
              - email
              - password
              properties:
                email:
                  type: string
                password:
                  type: string
      responses:
        '200':
          description: '{ok,account,csrf} + session cookies'
        '401':
          description: invalid credentials / unverified email
        '429':
          description: Rate limited (global 120/min/IP; stricter buckets on /mcp, webhook, auth). Sleep exactly Retry-After seconds, then retry.
          headers:
            Retry-After:
              schema:
                type: integer
              description: Seconds until the window resets — sleep this long, then retry
            RateLimit-Limit:
              schema:
                type: integer
              description: Requests allowed per window in this bucket
            RateLimit-Remaining:
              schema:
                type: integer
              description: Requests left in the current window (0 on 429)
            RateLimit-Reset:
              schema:
                type: integer
              description: Seconds until the window resets
      tags:
      - Account
      summary: Account login
      x-summary-source: derived
  /v1/account/logout:
    post:
      operationId: accountLogout
      security: []
      description: Revoke the session (session cookie + X-CSRF-Token required).
      responses:
        '200':
          description: logged out; cookies cleared
        '401':
          description: not signed in
        '403':
          description: missing/invalid CSRF
      tags:
      - Account
      summary: Account logout
      x-summary-source: derived
  /v1/account/me:
    get:
      operationId: accountMe
      security: []
      description: Current session's account + linked seller badge/KYC status + refundDue flag (drives the /account sequential CTA). Session cookie required.
      responses:
        '200':
          description: '{account, seller, refundDue}'
        '401':
          description: not signed in
      tags:
      - Account
      summary: Account me
      x-summary-source: derived
  /v1/account/profile:
    post:
      operationId: accountSetDisplayName
      security: []
      description: Set the seller's public display name {displayName} (≤60 chars, escaped). Session + CSRF.
      requestBody:
        required: true
        content:
          application/json:
            schema:
              type: object
              required:
              - displayName
              properties:
                displayName:
                  type: string
      responses:
        '200':
          description: '{ok,displayName}'
        '400':
          description: invalid name
        '401':
          description: not signed in
        '403':
          description: missing/invalid CSRF
      tags:
      - Account
      summary: Account set display name
      x-summary-source: derived
  /v1/account/password/reset-request:
    post:
      operationId: accountResetRequest
      security: []
      description: Request a password-reset link {email}. Enumeration-resistant generic 200; 503 until email configured.
      requestBody:
        required: true
        content:
          application/json:
            schema:
              type: object
              required:
              - email
              properties:
                email:
                  type: string
      responses:
        '200':
          description: generic message
        '400':
          description: invalid email
        '429':
          description: Rate limited (global 120/min/IP; stricter buckets on /mcp, webhook, auth). Sleep exactly Retry-After seconds, then retry.
          headers:
            Retry-After:
              schema:
                type: integer
              description: Seconds until the window resets — sleep this long, then retry
            RateLimit-Limit:
              schema:
                type: integer
              description: Requests allowed per window in this bucket
            RateLimit-Remaining:
              schema:
                type: integer
              description: Requests left in the current window (0 on 429)
            RateLimit-Reset:
              schema:
                type: integer
              description: Seconds until the window resets
        '503':
          description: email not enabled yet
      tags:
      - Account
      summary: Account reset request
      x-summary-source: derived
  /v1/account/password/reset:
    post:
      operationId: accountResetPassword
      security: []
      description: Complete a password reset {token,password}.
      requestBody:
        required: true
        content:
          application/json:
            schema:
              type: object
              required:
              - token
              - password
              properties:
                token:
                  type: string
                password:
                  type: string
                  description: ≥10 chars
      responses:
        '200':
          description: password updated
        '400':
          description: invalid/expired token or weak password
        '429':
          description: Rate limited (global 120/min/IP; stricter buckets on /mcp, webhook, auth). Sleep exactly Retry-After seconds, then retry.
          headers:
            Retry-After:
              schema:
                type: integer
              description: Seconds until the window resets — sleep this long, then retry
            RateLimit-Limit:
              schema:
                type: integer
              description: Requests allowed per window in this bucket
            RateLimit-Remaining:
              schema:
                type: integer
              description: Requests left in the current window (0 on 429)
            RateLimit-Reset:
              schema:
                type: integer
              description: Seconds until the window resets
      tags:
      - Account
      summary: Account reset password
      x-summary-source: derived
  /v1/account/badge/params:
    get:
      operationId: badgeWalletParams
      security: []
      description: Public, non-secret config the browser echoes to sign the EIP-3009 $20 badge payment (chain, USDC asset, payTo, amount, EIP-712 domain, the x402 v2 `accepted` requirement). Session.
      responses:
        '200':
          description: EIP-3009 payment params
      tags:
      - Account
      summary: Badge wallet params
      x-summary-source: derived
  /v1/account/badge/pay:
    post:
      operationId: badgeWalletPay
      security: []
      description: 'Pay the $20 badge with a browser wallet: submit the signed EIP-3009 PaymentPayload {payment}; server verify+settle via the facilitator → activate (ADR-0014). Session + CSRF; dedup on settlement tx.'
      requestBody:
        required: true
        content:
          application/json:
            schema:
              type: object
              required:
              - payment
              properties:
                payment:
                  type: object
      responses:
        '200':
          description: '{ok,tx,subscriptionUntil}'
        '400':
          description: missing payment / verify failed
        '401':
          description: not signed in
        '403':
          description: missing/invalid CSRF
        '429':
          description: Rate limited (global 120/min/IP; stricter buckets on /mcp, webhook, auth). Sleep exactly Retry-After seconds, then retry.
          headers:
            Retry-After:
              schema:
                type: integer
              description: Seconds until the window resets — sleep this long, then retry
            RateLimit-Limit:
              schema:
                type: integer
              description: Requests allowed per window in this bucket
            RateLimit-Remaining:
              schema:
                type: integer
              description: Requests left in the current window (0 on 429)
            RateLimit-Reset:
              schema:
                type: integer
              description: Seconds until the window resets
        '502':
          description: settlement failed
      tags:
      - Account
      summary: Badge wallet pay
      x-summary-source: derived
  /v1/account/badge/manual-params:
    get:
      operationId: badgeManualParams
      security: []
      description: 'Issue/return this account''s MANUAL payment intent (ADR-0019): platform USDC address + a crypto-random high-entropy unique amount $20.000001–$20.999999 (~10^6 values, unique among active intents, 60-min TTL) bound server-side to the account. Session.'
      responses:
        '200':
          description: '{payTo,asset,network,chainId,amountAtomic,amountUsd,expiresAt}'
        '401':
          description: not signed in
        '503':
          description: not configured for this network
      tags:
      - Account
      summary: Badge manual params
      x-summary-source: derived
  /v1/account/badge/pay-manual:
    post:
      operationId: badgeManualPay
      security: []
      description: 'Pay the $20 badge from ANY wallet/exchange: submit {txHash}; server reads the chain and credits the account the matching transfer amount was ISSUED to (intent-based attribution — pasting another''s hash credits them, not you). Session + CSRF; tx-deduped (ADR-0019). Read-only; never moves funds.'
      requestBody:
        required: true
        content:
          application/json:
            schema:
              type: object
              required:
              - txHash
              properties:
                txHash:
                  type: string
                  description: 0x + 64 hex
      responses:
        '200':
          description: '{ok,tx,subscriptionUntil}'
        '400':
          description: not verified / no matching intent / no tx
        '401':
          description: not signed in
        '403':
          description: missing/invalid CSRF
        '409':
          description: already processed / not your amount
        '429':
          description: Rate limited (global 120/min/IP; stricter buckets on /mcp, webhook, auth). Sleep exactly Retry-After seconds, then retry.
          headers:
            Retry-After:
              schema:
                type: integer
              description: Seconds until the window resets — sleep this long, then retry
            RateLimit-Limit:
              schema:
                type: integer
              description: Requests allowed per window in this bucket
            RateLimit-Remaining:
              schema:
                type: integer
              description: Requests left in the current window (0 on 429)
            RateLimit-Reset:
              schema:
                type: integer
              description: Seconds until the window resets
        '502':
          description: RPC error
      tags:
      - Account
      summary: Badge manual pay
      x-summary-source: derived
  /v1/account/badge/detect:
    post:
      operationId: badgeDetect
      security: []
      description: 'Auto-detect the manual payment (no hash to paste, ADR-0019): scans recent USDC Transfer logs to the platform wallet for this account''s intent amount → activates on a match. Session + CSRF. Read-only.'
      responses:
        '200':
          description: '{ok,found,...} — found:true activates, found:false keeps waiting'
        '401':
          description: not signed in
        '403':
          description: missing/invalid CSRF
        '409':
          description: no active intent (reload)
        '429':
          description: Rate limited (global 120/min/IP; stricter buckets on /mcp, webhook, auth). Sleep exactly Retry-After seconds, then retry.
          headers:
            Retry-After:
              schema:
                type: integer
              description: Seconds until the window resets — sleep this long, then retry
            RateLimit-Limit:
              schema:
                type: integer
              description: Requests allowed per window in this bucket
            RateLimit-Remaining:
              schema:
                type: integer
              description: Requests left in the current window (0 on 429)
            RateLimit-Reset:
              schema:
                type: integer
              description: Seconds until the window resets
        '502':
          description: chain error
      tags:
      - Account
      summary: Badge detect
      x-summary-source: derived
  /v1/account/kyc/start:
    post:
      operationId: accountKycStart
      security: []
      description: Start Didit identity verification AFTER paying the badge (payment-first; the seller is resolved from the session, ADR-0015). Session + CSRF.
      responses:
        '200':
          description: '{ok,verificationUrl,kycStatus:''pending''}'
        '401':
          description: not signed in
        '403':
          description: missing/invalid CSRF
        '409':
          description: pay the $20 badge first / already verified
        '502':
          description: could not start verification
        '503':
          description: KYC (Didit) not enabled yet
      tags:
      - Account
      summary: Account kyc start
      x-summary-source: derived
externalDocs:
  description: Agent skill file — what to run before acting on a token, an address or a counterparty (text/markdown, live prices and catalog)
  url: https://fiatdock.com/skill.md
x-payment-protocol:
  protocol: x402
  version: 2
  network: base
  asset: USDC
  payTo: '0xeB12bB2f52EeD33DBa6A00774E48324032Fd87C6'
  mode: per-call
  paid:
  - path: /v1/offramp/session
    method: POST
    priceUsd: 0.01
  - path: /v1/onramp/session
    method: POST
    priceUsd: 0.01
  - path: /v1/token/safety
    method: POST
    priceUsd: 0.0045
  - path: /v1/stablecoin/intel
    method: POST
    priceUsd: 0.002
  - path: /v1/chain/token-metadata
    method: POST
    priceUsd: 0.002
  - path: /v1/chain/gas-price
    method: POST
    priceUsd: 0.001
  - path: /v1/chain/block
    method: POST
    priceUsd: 0.001
  - path: /v1/chain/eth-balance
    method: POST
    priceUsd: 0.001
  - path: /v1/chain/usdc-balance
    method: POST
    priceUsd: 0.001
  - path: /v1/chain/tx-status
    method: POST
    priceUsd: 0.001
  - path: /v1/chain/address-intel
    method: POST
    priceUsd: 0.0045
  - path: /v1/chain/token-report
    method: POST
    priceUsd: 0.0045
  - path: /v1/web/read
    method: POST
    priceUsd: 0.0018
  - path: /v1/email/check
    method: POST
    priceUsd: 0.001
  - path: /v1/market/perp
    method: POST
    priceUsd: 0.001
  - path: /v1/markets/prediction
    method: POST
    priceUsd: 0.0045
  - path: /v1/defi/yields
    method: POST
    priceUsd: 0.001
  - path: /v1/fx/rates
    method: POST
    priceUsd: 0.001
  - path: /v1/chain/portfolio
    method: POST
    priceUsd: 0.0045
  - path: /v1/token/holders
    method: POST
    priceUsd: 0.0027
  - path: /v1/domain/intel
    method: POST
    priceUsd: 0.0045
  - path: /v1/web/contacts
    method: POST
    priceUsd: 0.0027
  - path: /v1/news/crypto
    method: POST
    priceUsd: 0.001
  - path: /v1/sec/filings
    method: POST
    priceUsd: 0.0027
  - path: /v1/text/prompt-check
    method: POST
    priceUsd: 0.0045
  - path: /v1/token/screener
    method: POST
    priceUsd: 0.009
  - path: /v1/papers/search
    method: POST
    priceUsd: 0.009
  - path: /v1/geo/satellite
    method: POST
    priceUsd: 0.009
  - path: /v1/web/seo-audit
    method: POST
    priceUsd: 0.009
  - path: /v1/x402/top
    method: POST
    priceUsd: 0.009
  - path: /v1/chain/ens
    method: POST
    priceUsd: 0.0027
  - path: /v1/time/convert
    method: POST
    priceUsd: 0.001
  - path: /v1/calendar/holidays
    method: POST
    priceUsd: 0.001
  - path: /v1/weather/forecast
    method: POST
    priceUsd: 0.0018
  - path: /v1/wiki/summary
    method: POST
    priceUsd: 0.0018
  - path: /v1/news/hackernews
    method: POST
    priceUsd: 0.0027
  - path: /v1/feed/read
    method: POST
    priceUsd: 0.0022
  - path: /v1/dev/package
    method: POST
    priceUsd: 0.0027
  - path: /v1/sec/financials
    method: POST
    priceUsd: 0.0045
  - path: /v1/token/verdict
    method: POST
    priceUsd: 0.009
  - path: /v1/market/backtest
    method: POST
    priceUsd: 0.009
  - path: /s/{id}
    method: POST
    priceUsd: null
    note: per-listing price; the 402 is authoritative
  free:
  - /v1/quote
  - /v1/token/price
  - /v1/orders/{partnerOrderId}
  - /v1/marketplace/services
  - /v1/marketplace/services/{id}
  - /v1/marketplace/demand
  - /v1/x402/search
  relay:
  - path: /v1/x402/call
    method: POST
    priceUsd: null
    note: carries the caller's PAYMENT-SIGNATURE to an index-listed x402 endpoint; that endpoint's 402 is authoritative and its payTo receives the money — FiatDock charges nothing here