Fish Data API
An OData v4 feed of auction lot prices captured from fish auctions.
The Fish Data API exposes fish-auction data as an OData v4 feed, making it easy to query, filter, and integrate data into tools like Power BI, Excel, or any OData-compatible client.
AuctionLots — the full daily lot catalogue scraped from the auction sheet, with
species, gear, seller, weight, the realised price per kilogram, and the matched buyer.
OData v4 over HTTPS
JSON (application/json)
API key via header or query param
5 000 rows per request
Authentication
Every request must include an API key. You can pass it either as an HTTP request header (recommended) or as a query parameter (useful for tools that cannot set custom headers, such as the Power BI Web connector).
Option 1 — HTTP header (recommended)
X-Api-Key: your-api-key-here
Option 2 — Query parameter
https://fish.metadata.is/odata/AuctionLots?api_key=your-api-key-here
Requests with a missing or invalid key receive a 401 Unauthorized response.
Base URL
https://fish.metadata.is/odata
The OData service root is /odata. All entity sets are relative to this path.
Endpoints
One read-only collection is available, supporting all OData query options listed below.
List auction lots
Returns a collection of auction lots — one row per lot from the daily auction sheet.
Get a single lot
Returns a single auction lot by its integer Id.
Fields
Auction Lots
| Field | Type | Description |
|---|---|---|
Id | Integer | Unique record identifier (auto-assigned). |
AuctionDate | Date | The auction trading day (YYYY-MM-DD). |
Species | String | Fish species (e.g. Þorskur — cod). |
SpeciesCondition | String | Condition the species group was sold under (e.g. Óslægt — ungutted). |
GroupTotalKg | Integer | Total kilograms offered in the species/condition group this lot belongs to. |
Lot | String | Lot identifier within the auction (e.g. 1-1). |
Gear | String | Fishing gear used (e.g. Lína — longline). |
Seller | String | Seller / vessel as reported by the auction. |
Condition | String | Lot condition grading. |
Size | String | Size grading of the fish. |
Age | String | Age / freshness of the catch (e.g. 1-dags — one day). |
Location | String | Auction market / landing location. |
WeightKg | Integer | Weight of this lot, in kilograms. |
PriceKrPerKg | Integer (nullable) | Realised price in ISK per kg. null until the auction has run. |
Buyer | String (nullable) | Buyer matched from the auction's buyer agreements. null if no match could be resolved. |
ScrapedAt | DateTimeOffset | UTC timestamp when the lot was scraped. |
PriceKrPerKg is only populated during and after the auction (around 17:00 Iceland time, Sunday to Friday). Lots fetched earlier in the day will have a null price.
Query Options
The following standard OData system query options are supported on both collections:
| Option | Description | Example |
|---|---|---|
$filter |
Filter rows by a boolean expression. | $filter=Buyer eq 'Jón Jónsson' |
$select |
Return only the specified fields. | $select=Lot,PriceKrPerKg |
$orderby |
Sort results. Append desc for descending. |
$orderby=Price desc |
$top |
Limit number of rows returned (max 1 000). | $top=100 |
$skip |
Skip the first N rows — use with $top to page through results. |
$skip=1000 |
$count |
Include total row count in the response. | $count=true |
Filter operators
| Operator | Meaning | Example |
|---|---|---|
eq | Equals | Buyer eq 'Jón Jónsson' |
ne | Not equals | Buyer ne 'Unknown' |
gt | Greater than | Price gt 500000 |
ge | Greater than or equal | Price ge 1000000 |
lt | Less than | Price lt 200000 |
le | Less than or equal | Price le 999999 |
and | Logical AND | Price gt 500000 and Buyer eq 'Jón' |
or | Logical OR | Lot eq 'A-001' or Lot eq 'B-002' |
Filtering
Filter by buyer name
GET /odata/AuctionLots?$filter=Buyer eq 'Jón Jónsson' X-Api-Key: your-api-key-here
Filter by lot number
GET /odata/AuctionLots?$filter=Lot eq '1-1' X-Api-Key: your-api-key-here
Filter by date range
GET /odata/AuctionLots?$filter=AuctionDate ge 2025-01-01 and AuctionDate lt 2025-02-01 X-Api-Key: your-api-key-here
Filter by minimum price
GET /odata/AuctionLots?$filter=PriceKrPerKg ge 1000 X-Api-Key: your-api-key-here
Example response
{
"@odata.context": "https://fish.metadata.is/odata/$metadata#AuctionLots",
"value": [
{
"Id": 1,
"AuctionDate": "2025-01-15",
"Lot": "42-1",
"Buyer": "Jón Jónsson",
"PriceKrPerKg": 1250
}
]
}
Selecting Fields
Use $select to return only the fields you need, reducing payload size.
GET /odata/AuctionLots?$select=Lot,Buyer,PriceKrPerKg X-Api-Key: your-api-key-here
{
"@odata.context": ".../$metadata#AuctionLots(Lot,Buyer,PriceKrPerKg)",
"value": [
{ "Lot": "42-1", "Buyer": "Jón Jónsson", "PriceKrPerKg": 1250 }
]
}
Sorting & Paging
Top 10 most expensive lots
GET /odata/AuctionLots?$orderby=PriceKrPerKg desc&$top=10 X-Api-Key: your-api-key-here
Paging through large result sets
The API returns at most 1 000 rows per request. When more results exist the response includes
an @odata.nextLink URL — follow it to fetch the next page. Use $count=true
on the first request to know the total up front.
$orderby when paging. Without it the database may return rows in a different order on each page, causing duplicates or gaps.
Page 1 — fetch first 1 000 rows and total count
GET /odata/AuctionLots?$orderby=Id&$count=true X-Api-Key: your-api-key-here
{
"@odata.context": "https://fish.metadata.is/odata/$metadata#AuctionLots",
"@odata.count": 3420,
"@odata.nextLink": "https://fish.metadata.is/odata/AuctionLots?$orderby=Id&$skip=1000",
"value": [ /* 1 000 records */ ]
}
Page 2 — follow nextLink or use $skip manually
GET /odata/AuctionLots?$orderby=Id&$skip=1000 X-Api-Key: your-api-key-here
Continue incrementing $skip by 1 000 until the response contains no @odata.nextLink — that means you have reached the last page.
Combined Queries
Query options can be combined freely in a single request.
Lots from a specific auction day, sorted by price
GET /odata/AuctionLots ?$filter=AuctionDate eq 2025-05-15 &$orderby=PriceKrPerKg desc &$select=Lot,Buyer,PriceKrPerKg &$count=true X-Api-Key: your-api-key-here
High-value lots for a specific buyer
GET /odata/AuctionLots ?$filter=Buyer eq 'Jón Jónsson' and PriceKrPerKg ge 500 &$orderby=AuctionDate desc &$top=100 X-Api-Key: your-api-key-here
More Auction Lots Examples
A few more common queries against AuctionLots. Note that AuctionDate is
a pure date, so filter it without quotes or a time component (e.g. AuctionDate eq 2026-06-05).
All cod lots on a given auction day
GET /odata/AuctionLots?$filter=Species eq 'Þorskur' and AuctionDate eq 2026-06-05 X-Api-Key: your-api-key-here
Highest price-per-kg lots (priced lots only)
GET /odata/AuctionLots?$filter=PriceKrPerKg ne null&$orderby=PriceKrPerKg desc&$top=10 X-Api-Key: your-api-key-here
Select just the columns you need
GET /odata/AuctionLots?$select=AuctionDate,Species,Lot,WeightKg,PriceKrPerKg&$orderby=AuctionDate desc X-Api-Key: your-api-key-here
Example response
{
"@odata.context": "https://fish.metadata.is/odata/$metadata#AuctionLots",
"value": [
{
"Id": 1,
"AuctionDate": "2026-06-05",
"Species": "Þorskur",
"SpeciesCondition": "Óslægt",
"GroupTotalKg": 6451,
"Lot": "1-1",
"Gear": "Lína",
"Seller": "2755 - Jón Ásbjörnsson RE-777",
"Condition": "Ó",
"Size": "Bl.Umál",
"Age": "1-dags",
"Location": "FMÍS / Þorl",
"WeightKg": 12,
"PriceKrPerKg": null,
"ScrapedAt": "2026-06-07T14:36:33Z"
}
]
}
Power BI Integration
Connect using the Web connector rather than the OData feed connector — it gives reliable control over the X-Api-Key request header, which the OData feed connector's Advanced options don't consistently apply.
value array into columns after connecting. It also doesn't support query folding — apply $filter, $select, $orderby, and $top directly in the URL instead. See Query Options for the syntax.
-
Open the Web connector
In Power BI Desktop: Get Data → Web. Choose Advanced so you can add a request header, and enter the URL:
URLhttps://fish.metadata.is/odata/AuctionLots -
Add the API key header
In the same Advanced panel, under HTTP request header parameters add:
Header name Value X-Api-Keyyour-api-key-here -
Shape the JSON into a table
Click OK. Power BI opens Power Query with the raw JSON response. Click into the
valuelist, then To Table, then use the expand button on the resulting column to break the records out into fields. -
Connect & load
Once the columns look right, click Close & Apply (or Load).
-
Schedule refresh (optional)
After publishing to the Power BI Service, set the data source credentials for this Web source to Anonymous, then re-add the
X-Api-Keyheader under Edit credentials → Advanced → HTTP request header parameters. Use a literal header value rather than one built from other query steps — Power BI's privacy/firewall checks can otherwise block scheduled refresh.
?api_key=your-key to the URL instead. See the Authentication section for details.