TREVL can fetch data from any REST API through the DataSource::Api data source. You configure a base URL and authentication, then reference API response fields in your YAML using the $ reference syntax.

Connecting an API

Register a data source with a name, base URL, and optional authentication:

Trevl::DataSource.register("myapi", Trevl::DataSource::Api.new(
  base_url: "https://api.example.com/v1",
  auth: Trevl::Auth::BearerToken.new(ENV["API_TOKEN"])
))

Then use that name in your TREVL components:

id: salary-chart
type: chart
api: myapi
api-parameters:
  profession:
    id: "43104"
    taxonomy: kldb
  location:
    country: DE
  time:
    start_month_offset: -12
    end_month_offset: 0
highchartsData:
  series:
  - data:
      y: "$salary.data.q50"

Reference Syntax

API data sources use a structured $-reference syntax with three levels: endpoint, scope, and field.

Standard form

$endpoint.data.field      # row data
$endpoint.meta.field      # response metadata

Examples:

y: "$salary.data.q50"                        # salary quantile from row
name: "$skills.data.label"                   # skill name from row
total: "$vacancies.meta.total_results"       # total from metadata

Resource-qualified form

When your API has multiple resource namespaces, prefix with the resource name:

$resource.endpoint.data.field
$resource.endpoint.meta.field

Examples:

y: "$professions.salary.data.q50"            # explicit resource
y: "$surveys.distribution.data.share"        # different resource

Legacy short form

For backward compatibility, the two-segment form still works:

y: "$salary.q50"    # equivalent to $salary.data.q50

api-parameters

The api-parameters section defines what gets sent in the request body. Only parameters you explicitly define are sent.

api-parameters:
  profession:
    id: "43104"
    taxonomy: kldb
  location:
    country: DE
  time:
    start_month_offset: -12
    end_month_offset: 0
  language: de
  limit: 25

Runtime parameter overrides

When a component is rendered in a specific context, parameters can be overridden at render time:

Trevl.render(yaml, params: {
  "param_override" => {"profession" => {"id" => "52101", "taxonomy" => "kldb"}}
})

This merges into the api-parameters, so the same component works for different contexts.

Discovering Fields

Before writing TREVL, you can discover what fields an API endpoint returns:

source = Trevl::DataSource.for("myapi")
source.field_names("salary")
# => ["date", "q10", "q25", "q50", "q75", "q90"]

This fetches a sample row and returns its keys. Use this to avoid guessing field names in your $ references.

Response Format

The API data source expects JSON responses in one of these formats:

Array of objects

[
  {"label": "Python", "value": 85},
  {"label": "Ruby", "value": 45}
]

Object with results/data key

{
  "results": [
    {"label": "Python", "value": 85}
  ],
  "metadata": {"total": 42}
}

Both results and data are recognized as the data array. Both metadata and meta are recognized as metadata.

Example: Chart from a REST API

id: skills-chart
type: chart
api: myapi
api-parameters:
  language: en
  limit: 10
highchartsData:
  chart:
    type: bar
  title:
    text: Top Skills
  series:
  - name: Relevance
    data:
      x: "$skills.data.label"
      y: "$skills.data.value"

Example: Table from a REST API

id: vacancy-table
type: table
api: myapi
api-parameters:
  location:
    country: DE
  limit: 20
tableData:
  headers: ["Title", "Company", "Location"]
  columns:
  - identifier: title
    value: "$vacancies.data.title"
  - identifier: company
    value: "$vacancies.data.company"
  - identifier: location
    value: "$vacancies.data.city"

Postprocess with API data

API components can use postprocess to transform the fetched data. The $result variable contains the rows:

postprocess: |
  $result = $result
    .sort(function(a, b) { return b.value - a.value; })
    .slice(0, 5);

Always guard against empty data – the API may return no results for certain parameters.

Computed fields with API data

Computed fields work the same way as with any data source. Arguments can reference $endpoint.data.* and $endpoint.meta.*:

computed:
- name: share_percent
  arguments:
    raw: "$skills.data.value"
  code: "Math.round(raw * 100) / 100"

Custom Authentication

The Auth::BearerToken class covers most APIs. For other auth methods, pass any object that responds to #apply(headers, url:):

class MyApiKeyAuth
  def initialize(key)
    @key = key
  end

  def apply(headers, url: nil)
    headers["X-API-Key"] = @key
  end
end

Trevl::DataSource.register("myapi", Trevl::DataSource::Api.new(
  base_url: "https://api.example.com",
  auth: MyApiKeyAuth.new(ENV["API_KEY"])
))