openapi: 3.0.3
info:
  title: SoloOutpost Visa & Tax API
  version: 1.0.0
  description: >-
    Mobility and taxation data for ~150 countries, built for solopreneurs and
    freelancers. For any passport, list every country you can relocate to with
    the tourist-visa access that applies to that passport, digital nomad and
    entrepreneur visa routes, income requirements, taxation basis, and a
    Solopreneur Friendliness score. Also exposes the full per-country tax and
    cost dataset.
servers:
  - url: https://solooutpost.com/api
    description: Production
tags:
  - name: Mobility
    description: Relocation and visa options by passport
  - name: Countries
    description: Per-country tax, cost and visa dataset
paths:
  /mobility:
    get:
      operationId: listNationalities
      tags: [Mobility]
      summary: List all covered nationalities
      description: Returns every passport for which a mobility profile exists.
      responses:
        '200':
          description: Array of nationalities
          content:
            application/json:
              schema:
                type: array
                items: { $ref: '#/components/schemas/NationalityIndexEntry' }
              example: [{"slug":"american","demonym":"American","passport":"United States","iso":"US","count":148},{"slug":"indian","demonym":"Indian","passport":"India","iso":"IN","count":148},{"slug":"russian","demonym":"Russian","passport":"Russia","iso":"RU","count":148}]
  /mobility/{nationality}:
    get:
      operationId: getMobilityByNationality
      tags: [Mobility]
      summary: Relocation options for a passport
      description: >-
        For the given nationality (demonym slug, e.g. "russian"), returns all
        destination countries ranked by Solopreneur Friendliness score, each
        annotated with that passport's entry route and visa details.
      parameters:
        - name: nationality
          in: path
          required: true
          description: Nationality demonym slug, e.g. russian, indian, german.
          schema: { type: string, example: russian }
        - name: nomad
          in: query
          required: false
          description: If true, only destinations with a digital nomad visa.
          schema: { type: boolean }
        - name: maxIncome
          in: query
          required: false
          description: Only destinations whose nomad-visa monthly income minimum is at or below this USD value.
          schema: { type: integer, example: 3000 }
      responses:
        '200':
          description: Ranked destinations for the passport
          content:
            application/json:
              schema: { $ref: '#/components/schemas/MobilityProfile' }
              example: {"passport":"Russia","demonym":"Russian","slug":"russian","iso":"RU","generated_from":"passport-index-dataset + SoloOutpost research data","count":148,"destinations":[{"slug":"united-arab-emirates","name":"United Arab Emirates","iso":"AE","region":"Middle East","friendliness_score":90,"nomad_visa":true,"entrepreneur_visa":true,"nomad_income_usd":3500,"taxation_basis":"territorial","expat_regime_name":null,"entry_category":"visa_free","entry_label":"Visa-free, 90 days","entry_days":90,"entry_note":null},{"slug":"georgia","name":"Georgia","iso":"GE","region":"Europe","friendliness_score":75,"nomad_visa":true,"entrepreneur_visa":false,"nomad_income_usd":2000,"taxation_basis":"territorial","expat_regime_name":"Small Business Status (1% turnover tax up to GEL 500,000)","entry_category":"visa_free","entry_label":"Visa-free, 360 days","entry_days":360,"entry_note":null}]}
        '404':
          description: Nationality not covered
          content:
            application/json:
              schema: { $ref: '#/components/schemas/Error' }
  /countries:
    get:
      operationId: listCountries
      tags: [Countries]
      summary: List all countries
      description: Slim list of the ~150 countries with headline tax and score fields.
      responses:
        '200':
          description: Array of countries
          content:
            application/json:
              schema:
                type: array
                items: { $ref: '#/components/schemas/CountrySlim' }
              example: [{"slug":"united-arab-emirates","name":"United Arab Emirates","iso_code":"AE","region":"Middle East","friendliness_score":90,"pit_top_rate":0,"cit_rate":9,"capital_gains_rate":0,"vat_standard_rate":5,"taxation_basis":"territorial","ss_self_employed_mandatory":"no","exit_tax":"no","digital_nomad_visa":true,"entrepreneur_visa":true,"dnv_income_requirement_usd":3500,"cost_of_living_index":55.2,"internet_speed_mbps":300,"english_proficiency":"high"}]
  /country/{slug}:
    get:
      operationId: getCountry
      tags: [Countries]
      summary: Full data for one country
      description: Every stored field for a single country (tax, social security, exit tax, visas, cost, lifestyle).
      parameters:
        - name: slug
          in: path
          required: true
          description: Country slug, e.g. portugal, united-arab-emirates.
          schema: { type: string, example: portugal }
      responses:
        '200':
          description: Full country record
          content:
            application/json:
              schema: { $ref: '#/components/schemas/CountryFull' }
              example: {"slug":"portugal","name":"Portugal","iso_code":"PT","region":"Europe","friendliness_score":50,"taxation_basis":"worldwide","pit_top_rate":48,"cit_rate":19,"capital_gains_rate":28,"vat_standard_rate":23,"ss_self_employed_mandatory":"yes","exit_tax":"conditional","digital_nomad_visa":true,"dnv_income_requirement_usd":3975,"entrepreneur_visa":true,"special_expat_regime_name":"IFICI (NHR successor); legacy NHR grandfathered before 2024","cost_of_living_index":48.8,"internet_speed_mbps":170,"english_proficiency":"high"}
        '404':
          description: Country not found
          content:
            application/json:
              schema: { $ref: '#/components/schemas/Error' }
  /citizenship:
    get:
      operationId: listCitizenship
      tags: [Citizenship]
      summary: All citizenship-by-investment programs
      description: Every country that grants a passport for investment or donation, with costs, criteria, status and restricted nationalities.
      responses:
        '200':
          description: Citizenship-by-investment dataset
          content:
            application/json:
              schema: { type: object }
  /citizenship/{slug}:
    get:
      operationId: getCitizenship
      tags: [Citizenship]
      summary: One citizenship-by-investment program
      parameters:
        - name: slug
          in: path
          required: true
          description: Program slug, e.g. turkey, dominica, grenada.
          schema: { type: string, example: turkey }
      responses:
        '200':
          description: One program
          content: { application/json: { schema: { type: object } } }
        '404':
          description: Program not found
          content: { application/json: { schema: { $ref: '#/components/schemas/Error' } } }
  /golden-visas:
    get:
      operationId: listGoldenVisas
      tags: [Golden Visas]
      summary: All golden-visa (residency-by-investment) programs
      description: Around 70 jurisdictions with investment thresholds, residency terms, path to citizenship and status.
      responses:
        '200':
          description: Golden-visa dataset
          content:
            application/json:
              schema: { type: object }
  /golden-visas/{slug}:
    get:
      operationId: getGoldenVisa
      tags: [Golden Visas]
      summary: One golden-visa program
      parameters:
        - name: slug
          in: path
          required: true
          description: Program slug, e.g. portugal, uae, greece.
          schema: { type: string, example: portugal }
      responses:
        '200':
          description: One program
          content: { application/json: { schema: { type: object } } }
        '404':
          description: Program not found
          content: { application/json: { schema: { $ref: '#/components/schemas/Error' } } }
components:
  schemas:
    NationalityIndexEntry:
      type: object
      properties:
        slug: { type: string, example: russian }
        demonym: { type: string, example: Russian }
        passport: { type: string, example: Russia }
        iso: { type: string, example: RU }
        count: { type: integer, example: 149 }
    Destination:
      type: object
      properties:
        slug: { type: string, example: georgia }
        name: { type: string, example: Georgia }
        iso: { type: string, nullable: true, example: GE }
        region: { type: string, nullable: true, example: Europe }
        friendliness_score: { type: integer, example: 75 }
        nomad_visa: { type: boolean, example: true }
        entrepreneur_visa: { type: boolean, example: false }
        nomad_income_usd: { type: integer, nullable: true, example: 2000 }
        taxation_basis: { type: string, nullable: true, example: territorial }
        expat_regime_name: { type: string, nullable: true, example: Small Business Status }
        entry_category:
          type: string
          description: Visa route for this passport into the destination.
          enum: [free_movement, residence_agreement, visa_free, voa, evisa, eta, visa_required, no_admission, home, unknown]
          example: visa_free
        entry_label: { type: string, example: 'Visa-free, 360 days' }
        entry_days: { type: integer, nullable: true, example: 360 }
        entry_note: { type: string, nullable: true }
    MobilityProfile:
      type: object
      properties:
        passport: { type: string, example: Russia }
        demonym: { type: string, example: Russian }
        slug: { type: string, example: russian }
        iso: { type: string, example: RU }
        generated_from: { type: string }
        count: { type: integer, example: 149 }
        destinations:
          type: array
          items: { $ref: '#/components/schemas/Destination' }
    CountrySlim:
      type: object
      properties:
        slug: { type: string, example: portugal }
        name: { type: string, example: Portugal }
        iso_code: { type: string, example: PT }
        region: { type: string, example: Europe }
        friendliness_score: { type: integer, example: 68 }
        pit_top_rate: { type: number, example: 48 }
        taxation_basis: { type: string, example: worldwide }
        digital_nomad_visa: { type: boolean, example: true }
    CountryFull:
      type: object
      description: Full country record. All fields from the SoloOutpost dataset.
      additionalProperties: true
      properties:
        country_name: { type: string, example: Portugal }
        iso_code: { type: string, example: PT }
        region: { type: string, example: Europe }
        friendliness_score: { type: integer, example: 68 }
    Error:
      type: object
      properties:
        error: { type: string, example: not_found }
        message: { type: string }
