---
name: ssb-vessels-foreign-going-trade-ingestion
description: "How to get Statistics Norway vessels in foreign-going trade (StatBank 07321) data into a pandas DataFrame and Parquet: access, the request, the format, limits, quirks and terms."
---

# Query SSB StatBank table 07321 via PxWebApi

Source entry: https://signal-lab.qdt.ai/datasets/ssb-vessels-foreign-going-trade
Provider: https://www.ssb.no/en/statbank/table/07321
Checked against the provider's documentation: 2026-11-06

## Access
- No key. POST JSON query to data.ssb.no/api/v0/en/table/07321.

## Request
```bash
curl -sS -X POST 'https://data.ssb.no/api/v0/en/table/07321' -H 'Content-Type: application/json' -d '{"query":[{"code":"ContentsCode","selection":{"filter":"item","values":["Reisecert"]}},{"code":"Tid","selection":{"filter":"top","values":["5"]}}],"response":{"format":"json-stat2"}}' 
```

## Format
JSON-stat2 table with ContentsCode (freight/charter measures) and Tid (year).

## Load into pandas and Parquet
Needs Python 3 with requests, pandas and pyarrow.
```python
"""SSB StatBank 07321 vessels in foreign-going trade sample query (JSON-stat2 → labeled rows)."""
import requests
import pandas as pd
from itertools import product

URL = "https://data.ssb.no/api/v0/en/table/07321"
query = {
    "query": [
        {"code": "ContentsCode", "selection": {"filter": "item", "values": ["Reisecert", "Fraktkontr", "Linjefrakt"]}},
        {"code": "Tid", "selection": {"filter": "top", "values": ["10"]}},
    ],
    "response": {"format": "json-stat2"},
}
r = requests.post(URL, json=query, timeout=60)
r.raise_for_status()
js = r.json()
vals = js.get("value") or []
dims = js.get("id") or []
size = js.get("size") or []
dimension = js.get("dimension") or {}

def labels_for(dim_id: str):
    cat = dimension[dim_id]["category"]
    index = cat["index"]
    # index maps category-id -> position
    by_pos = [None] * len(index)
    for key, pos in index.items():
        by_pos[pos] = key
    lab = cat.get("label") or {}
    return by_pos, lab

# JSON-stat stores values in row-major order with the last dimension changing fastest.
axes = [list(range(s)) for s in size]
rows = []
for coords in product(*axes):
    flat = 0
    mul = 1
    for c, s in zip(reversed(coords), reversed(size)):
        flat += c * mul
        mul *= s
    row = {"value": vals[flat]}
    for dim_id, c in zip(dims, coords):
        by_pos, lab = labels_for(dim_id)
        cid = by_pos[c]
        row[dim_id] = cid
        row[f"{dim_id}_label"] = lab.get(cid, cid)
    rows.append(row)

df = pd.DataFrame(rows)
print("HTTP", r.status_code, "rows", len(df), "label", js.get("label"))
print(df.head().to_string(index=False))
df.to_parquet("ssb_07321_sample.parquet", index=False)

```
Run by us on 2026-11-06 (python 3 | pandas | requests). Result: SSB API meta for table 07321 returned HTTP 200 on 2026-11-06 with contents codes including Reisecert (Voyage freights) and years from 2001.

## Limits
- Not stated numeric rate limit on the checked SSB API page.

## Quirks
- JSON-stat2 value[] is unlabeled until expanded with ContentsCode and Tid dimensions into columns.
- SSB APIs use CC BY 4.0 — attribute Statistics Norway.

## Terms and attribution
- SSB: "Like the rest of ssb.no, the APIs use the license CC BY 4.0."
- Table 07321 title: "Vessels in foreign going trade (NOK million), by contents and year."
- Terms page: https://creativecommons.org/licenses/by/4.0/

## Sources
- https://www.ssb.no/en/omssb/tjenester-og-verktoy/api: "Like the rest of ssb.no, the APIs use the license CC BY 4.0"
- https://www.ssb.no/en/statbank/table/07321: "Vessels in foreign going trade (NOK million), by contents and year"

## Help improve this skill
Missing a source, or see something to improve? Call the MCP tool suggest_source or feedback (or POST /api/suggest or /api/feedback). Reviewed ideas: https://signal-lab.qdt.ai/agent-suggestions

Information for educational purposes only. Free tiers, limits and licenses belong to the providers and may change; check the provider's own terms before using the data.
