Opplevagent Discovery API

Read-only REST discovery over verified Norwegian experiences and gårdssalg producers: intent discovery with county, municipality, category, weather, season, indoor/outdoor, group size, age, price, duration, language and near-me (lat/lng/radius) filters; a category list with live counts; and a single-experience lookup by UUID. Anonymous, with IETF RateLimit headers on every response (300 requests per 900 s; 900 with the optional free X-API-Key). The OpenAPI also declares the A2A card, the A2A JSON-RPC endpoint and llms.txt as operations.

Operations 7

GET /api/opplevelser/discover Discover experiences (intent discovery) #
GET /api/opplevelser/categories List experience categories #
GET /api/opplevelser/{id} Get a single experience by ID #
GET /a2a A2A agent card (health check) #
POST /a2a A2A JSON-RPC 2.0 endpoint #
GET /.well-known/agent-card.json A2A Agent Card (well-known) #
GET /llms.txt LLM-friendly site overview #

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/discovery-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

opplevagent-no-openapi.yml Raw ↑
# Faithful YAML rendering of https://opplevagent.no/openapi.json fetched 2026-09-19 (HTTP 200, application/json, 11838 bytes).
# Content is unchanged from openapi/_original/opplevagent-no-openapi.json; API Evangelist enhancements live in overlays/, never here.
openapi: 3.1.0
info:
  title: Opplevagent API
  description: REST API for Norwegian experience and activity discovery. Experiences are harvested from curated sources and provider-verified against Brønnøysundregistrene. All read endpoints are public; no authentication required.
  version: 0.1.0
  contact:
    url: https://opplevagent.no
  license:
    name: CC0 (Brreg data)
    url: https://creativecommons.org/publicdomain/zero/1.0/
servers:
- url: https://opplevagent.no
  description: Production
paths:
  /api/opplevelser/discover:
    get:
      operationId: discoverExperiences
      summary: Discover experiences (intent discovery)
      description: «Hva kan vi finne på i [sted]» — intent discovery over published experiences. All parameters are optional and combinable. Only verified experiences whose provider is brreg-active and whose confidence is medium/high are surfaced. `category=gardssalg_smaking` routes to a distinct vertical — Brreg-registered farm-sale drink producers (gårdssalg) stored separately from `experiences` — and returns `vertical:"gardssalg"` with GardssalgProducer-shaped rows instead (see `producer_type`/`booking_live` parameters and the GardssalgProducer schema below).
      parameters:
      - name: fylke
        in: query
        description: County name (e.g. «Oslo», «Troms»)
        schema:
          type: string
        example: Troms
      - name: kommune
        in: query
        description: Municipality name (e.g. «Tromsø»)
        schema:
          type: string
        example: Tromsø
      - name: category
        in: query
        description: Category slug (e.g. «dyreliv_safari», «natur_friluft»). «gardssalg_smaking» routes to the gårdssalg producer vertical instead of `experiences`.
        schema:
          type: string
        examples:
          experience:
            value: dyreliv_safari
            summary: Regular experience category
          gardssalg:
            value: gardssalg_smaking
            summary: Gårdssalg (farm-sale drink producer) vertical
      - name: producer_type
        in: query
        description: 'Gårdssalg-only: producer type filter (e.g. «bryggeri», «sideri», «vingård»). Ignored outside `category=gardssalg_smaking`.'
        schema:
          type: string
        example: sideri
      - name: booking_live
        in: query
        description: 'Gårdssalg-only: pass literal `true` to only return producers with live direct booking (omitted = no filter on this column, NOT «only paused»). Ignored outside `category=gardssalg_smaking`.'
        schema:
          type: boolean
      - name: q
        in: query
        description: 'Gårdssalg-only: free-text lookup of ONE specific producer by name and/or place (e.g. «Fjordgard Bryggeri», «Egge gård Steinkjer»). Every word must match the producer''s name, URL slug, place (poststed) or municipality; exact name matches rank first. Use the returned `id` as `provider_id` when booking. Ignored outside `category=gardssalg_smaking`.'
        schema:
          type: string
          maxLength: 200
        example: Fjordgard Bryggeri
      - name: indoor_outdoor
        in: query
        description: Indoor / outdoor preference
        schema:
          type: string
          enum:
          - indoor
          - outdoor
          - both
      - name: weather
        in: query
        description: Weather hint — rain/snow prefer indoor & weather-independent
        schema:
          type: string
          enum:
          - rain
          - snow
          - clear
          - any
      - name: season
        in: query
        description: Season (e.g. «summer», «winter»)
        schema:
          type: string
        example: winter
      - name: group_size
        in: query
        description: Number of people in the group
        schema:
          type: integer
          minimum: 1
      - name: age
        in: query
        description: Age of the youngest participant
        schema:
          type: integer
          minimum: 0
      - name: max_price
        in: query
        description: Maximum price (NOK)
        schema:
          type: integer
          minimum: 1
      - name: duration_max
        in: query
        description: Maximum duration (minutes)
        schema:
          type: integer
          minimum: 1
      - name: language
        in: query
        description: Required language (e.g. «en», «no»)
        schema:
          type: string
      - name: lat
        in: query
        description: Origin latitude for a near-me search (decimal degrees). Must be given together with lng.
        schema:
          type: number
          minimum: -90
          maximum: 90
        example: 69.65
      - name: lng
        in: query
        description: Origin longitude for a near-me search (decimal degrees). Must be given together with lat.
        schema:
          type: number
          minimum: -180
          maximum: 180
        example: 18.95
      - name: radius_km
        in: query
        description: Max distance from lat/lng in kilometers. Only applies when lat/lng are given.
        schema:
          type: number
          exclusiveMinimum: 0
          maximum: 5000
        example: 50
      - name: sort
        in: query
        description: '''distance'' — sort ascending by distance from lat/lng (already the default whenever lat/lng are given).'
        schema:
          type: string
          enum:
          - distance
      - name: limit
        in: query
        description: Max results (default 20, max 100)
        schema:
          type: integer
          default: 20
          minimum: 1
          maximum: 100
      responses:
        '200':
          description: Discovery result — `vertical` and the shape of `results[]` depend on `category` (see GardssalgProducer for the gårdssalg branch).
          content:
            application/json:
              schema:
                type: object
                properties:
                  vertical:
                    type: string
                    enum:
                    - experiences
                    - gardssalg
                  query:
                    type: object
                  count:
                    type: integer
                  results:
                    type: array
                    items:
                      oneOf:
                      - $ref: '#/components/schemas/Experience'
                      - $ref: '#/components/schemas/GardssalgProducer'
              examples:
                gardssalg:
                  summary: category=gardssalg_smaking&fylke=Vestland
                  value:
                    vertical: gardssalg
                    query:
                      fylke: Vestland
                    count: 1
                    results:
                    - navn: Eksempel Sideri
                      fylke: Vestland
                      kommune: Ulvik
                      producer_type: sideri
                      lat: 60.57
                      lon: 6.9
                      geocode_confidence: high
                      booking:
                        live: false
                        mode: paused
                        note: Reservasjoner åpner snart; ta kontakt via profilsiden. / Bookings open soon; visit the profile page to get in touch.
                      profile_url: https://opplevagent.no/kategori/gardssalg/produsent/eksempel-sideri--abc123
        '400':
          description: Invalid query parameters
  /api/opplevelser/categories:
    get:
      operationId: listExperienceCategories
      summary: List experience categories
      description: Returns distinct categories with the count of published experiences in each.
      responses:
        '200':
          description: Array of category objects
          content:
            application/json:
              schema:
                type: object
                properties:
                  categories:
                    type: array
                    items:
                      type: object
                      properties:
                        category:
                          type: string
                        count:
                          type: integer
  /api/opplevelser/{id}:
    get:
      operationId: getExperience
      summary: Get a single experience by ID
      parameters:
      - name: id
        in: path
        required: true
        description: Experience UUID
        schema:
          type: string
      responses:
        '200':
          description: Experience object
          content:
            application/json:
              schema:
                type: object
                properties:
                  experience:
                    $ref: '#/components/schemas/Experience'
        '404':
          description: Not found
  /a2a:
    get:
      operationId: getExperiencesA2ACard
      summary: A2A agent card (health check)
      responses:
        '200':
          description: Agent card JSON
          content:
            application/json:
              schema:
                type: object
    post:
      operationId: experiencesA2AJsonRpc
      summary: A2A JSON-RPC 2.0 endpoint
      requestBody:
        required: true
        content:
          application/json:
            schema:
              type: object
              required:
              - jsonrpc
              - method
              - id
              properties:
                jsonrpc:
                  type: string
                  enum:
                  - '2.0'
                method:
                  type: string
                  enum:
                  - message/send
                  - tasks/send
                params:
                  type: object
                id:
                  type:
                  - string
                  - number
            examples:
              discover:
                summary: Discover experiences by county and weather
                value:
                  jsonrpc: '2.0'
                  method: message/send
                  params:
                    message:
                      text: hva kan vi finne på i Oslo når det regner
                  id: '1'
      responses:
        '200':
          description: JSON-RPC response
          content:
            application/json:
              schema:
                type: object
                properties:
                  jsonrpc:
                    type: string
                  result:
                    type: object
                  error:
                    type: object
                  id:
                    type:
                    - string
                    - number
  /.well-known/agent-card.json:
    get:
      operationId: getExperiencesAgentCardWellKnown
      summary: A2A Agent Card (well-known)
      responses:
        '200':
          description: Agent card
          content:
            application/json:
              schema:
                type: object
  /llms.txt:
    get:
      operationId: getExperiencesLlmsTxt
      summary: LLM-friendly site overview
      responses:
        '200':
          description: Plain-text overview for LLMs
          content:
            text/plain:
              schema:
                type: string
components:
  schemas:
    Experience:
      type: object
      properties:
        id:
          type: string
          description: UUID
        title:
          type: string
          description: Experience title
        category:
          type: string
          nullable: true
        fylke:
          type: string
          nullable: true
          description: County
        kommune:
          type: string
          nullable: true
          description: Municipality
        indoor_outdoor:
          type: string
          enum:
          - indoor
          - outdoor
          - both
          nullable: true
        duration_min:
          type: integer
          nullable: true
          description: Minimum duration (minutes)
        price_from:
          type: integer
          nullable: true
          description: Price from (NOK)
        price_band:
          type: string
          nullable: true
        booking_url:
          type: string
          nullable: true
        confidence:
          type: string
          enum:
          - high
          - medium
          - low
          nullable: true
        tags:
          type: array
          description: Derived cross-cutting filter tags (additive-only; computed from existing fields).
          items:
            type: string
            enum:
            - familievennlig
            - gratis
            - under-300
            - tilgjengelig
            - værsikker
            - sesong
        distance_km:
          type: number
          nullable: true
          description: 'Distance from the caller''s lat/lng origin, in kilometers (rounded to 1 decimal). Only present when lat/lng were given in the request. Never fabricated: rows with no geocoded location are excluded from the result entirely rather than shown with a missing/guessed distance.'
        geo_precision:
          type: string
          enum:
          - address
          - kommune
          nullable: true
          description: How this row's location (and therefore distance_km) was derived. 'address' = geocoded from the provider's exact street address (precise). 'kommune' = a municipality centroid (approximate — do not present distance_km as exact for these rows). Only present when lat/lng were given.
    GardssalgProducer:
      type: object
      description: A gårdssalg (farm-sale drink producer) row — returned by `/api/opplevelser/discover?category=gardssalg_smaking` and the `discover_gardssalg` MCP tool. Stored in `experience_providers`, not `experiences` — never mix with the Experience schema.
      properties:
        id:
          type: string
          description: The producer's id — the `provider_id` for `POST /api/opplevelser/book` and the `book_gardssalg` MCP tool.
        navn:
          type: string
        fylke:
          type: string
          nullable: true
        kommune:
          type: string
          nullable: true
        producer_type:
          type: string
          nullable: true
        lat:
          type: number
          nullable: true
        lon:
          type: number
          nullable: true
        geocode_confidence:
          type: string
          enum:
          - high
          - medium
          - low
          - no_match
          - approximate
          nullable: true
          description: Provider-address geocode quality (`experience_providers.geocode_confidence` — distinct from the Experience schema's `geo_precision`, which uses 'address'/'kommune' instead). 'high'/'medium'/'low' come from the address-geocoding step; 'approximate' is a kommune-centroid fallback; 'no_match' means no coordinates could be resolved (lat/lon are null in that case).
        booking:
          type: object
          description: Honest booking status — never claims an active booking flow before the dark-launch gate opens.
          properties:
            live:
              type: boolean
            mode:
              type: string
              enum:
              - request
              - paused
            note:
              type: string
        profile_url:
          type: string
          nullable: true
        distance_km:
          type: number
          nullable: true
          description: Only present when lat/lng were given in the request (near-me search).