Skip to main content
All CollectionsUsing the Ocean Wise Sightings Network API
Using the Ocean Wise Sightings Network API
Using the Ocean Wise Sightings Network API

Introductory article to help potential users of the OWSN API access and visualize data through different systems.

Updated over a week ago

Overview:

The Ocean Wise Sightings Network API provides access to high-quality, cleaned, and collated whale presence data to support conservation efforts, policymaking, environmental assessments, and marine operations from the Ocean Wise Sightings Network database (OWSN).

This service is designed to facilitate easy access to marine mammal presence data for conservation purposes, while maintaining ethical data-sharing practices and supporting contributors.

Our API delivers real-time and historical whale presence data, processed and structured for seamless integration into existing workflows. Users benefit from:

  • Cleaned and validated data

  • Standardized API access with documentation and sample code (R, Python, VBA, Power BI) for access, data visualization, and analysis

QGIS:

Access

To access the API directly in QGIS and visualize data you will utilize the QGIS Python Console.

The QGIS Python Console is an interactive shell for Python command executions. It also has a Python file editor that allows you to edit and save your Python scripts.

  1. To open the console go to Plugins ► Python Console (Ctrl+Alt+P). Once opened, it will look like the image below.

  2. Click the "Show editor" button in the console to bring up a blank script. Here you will enter and run your code. Your session should now look like the below image (you may have to drag and rearrange the size of the console and windows to view the script editor).

  3. Copy the code below paste into the script editor. NOTE - you will need to update the API_KEY, DATEFROM , and DATETO for the code to work (see below callout for a warning before you run this).

    #```python
    import requests
    import json
    from qgis.core import QgsVectorLayer, QgsField, QgsFeature, QgsPointXY, QgsGeometry, QgsProject, QgsCategorizedSymbolRenderer, QgsRendererCategory, QgsSymbol
    from PyQt5.QtCore import QVariant
    from PyQt5.QtGui import QColor

    # API Request
    BASE_URL = "https://sightingsapi.ocean.org/sightings"
    API_KEY = "your_api_key_here" # REPLACE WITH GIVEN API KEY
    LIMIT = 1000
    PAGE = 1
    DATEFROM = "2025-01-01T00:00:00Z" # UPDATE THIS
    DATETO = "2025-03-01T00:00:00Z" # UPDATE THIS
    all_data = []

    params = {
    "api_key": API_KEY,
    "limit": LIMIT,
    "page": PAGE,
    "sightedFrom": DATEFROM,
    "sightedTo": DATETO
    }
    headers = {"x-api-key": API_KEY}

    while True:
    response = requests.get(BASE_URL, params=params, headers=headers)
    if response.status_code != 200:
    print(f"Error: {response.status_code}")
    break

    data = response.json()
    records = data.get("sightings", [])

    if not records:
    break

    all_data.extend(records)
    PAGE += 1
    params["page"] = PAGE


    # Species Lookup Table (speciesID → speciesName)
    species_mapping = {
    1: "Killer whale",
    2: "Humpback whale",
    3: "Grey whale",
    4: "Minke whale",
    5: "Fin whale",
    6: "Sperm whale",
    7: "Blue whale",
    8: "Sei whale",
    9: "North Pacific right whale",
    10: "Baird's beaked whale",
    11: "Cuvier's beaked whale",
    12: "Other rare species",
    13: "Unidentified whale",
    14: "Killer whale",
    15: "Harbour porpoise",
    16: "Dall's porpoise",
    17: "Pacific white-sided dolphin",
    18: "Risso's dolphin",
    19: "Northern right whale dolphin",
    20: "False killer whale",
    21: "Common dolphin (short or long beaked)",
    22: "Unidentified dolphin or porpoise",
    23: "Leatherback sea turtle",
    24: "Green sea turtle",
    25: "Olive ridley sea turtle",
    26: "Loggerhead sea turtle",
    27: "Unidentified sea turtle",
    }

    # Create Memory Layer in QGIS
    layer = QgsVectorLayer("Point?crs=EPSG:4326", "Whale Sightings", "memory")
    provider = layer.dataProvider()

    # Add fields (columns)
    provider.addAttributes([
    QgsField("speciesID", QVariant.Int),
    QgsField("speciesName", QVariant.String),
    QgsField("sightedDate", QVariant.String),
    QgsField("travelDirection", QVariant.String),
    QgsField("ecotype", QVariant.String),
    QgsField("sourceEntity", QVariant.String),
    QgsField("idConfidence", QVariant.String)
    ])
    layer.updateFields()

    # Process and Add Data Points
    features = []
    for record in all_data:
    try:
    lon = float(record.get("longitude", 0))
    lat = float(record.get("latitude", 0))

    # Skip invalid coordinates
    if lon == 0 or lat == 0:
    print(f"Skipping invalid coordinates: {record}")
    continue

    species_id = int(record.get("speciesId", 0)) # Convert ID to int
    species_name = species_mapping.get(species_id, "Other rare species") # Default to "Other rare species"
    direction = record.get("travelDirection", "Unknown")
    ecotype = record.get("ecotype", "Unknown")
    source_entity = record.get("sourceEntity", "Unknown")
    id_confidence = record.get("idConfidence", "Unknown")

    feature = QgsFeature()
    point = QgsPointXY(lon, lat)
    feature.setGeometry(QgsGeometry.fromPointXY(point))

    feature.setAttributes([
    species_id,
    species_name,
    record.get("sightedDate", "N/A"),
    direction,
    ecotype,
    source_entity,
    id_confidence
    ])
    features.append(feature)
    except Exception as e:
    print(f"Error processing record: {record}\n{e}")

    if features:
    provider.addFeatures(features)
    layer.updateExtents()
    QgsProject.instance().addMapLayer(layer)
    print(f"✅ Loaded {len(features)} whale sightings into QGIS.")
    else:
    print("⚠️ No valid data points were loaded. Check API response.")

    layer.commitChanges()
    layer.updateExtents()
    QgsProject.instance().addMapLayer(layer)

    # Define Color Mapping for Species
    species_colors = {
    "Killer whale": "black",
    "Humpback whale": "red",
    "Grey whale": "gray",
    "Minke whale": "lightblue",
    "Fin whale": "#A7C796" # Light moss green
    }

    # Create Categorized Symbol Renderer
    categories = []

    for species_id, species_name in species_mapping.items():
    # Default color: purple (for "Other Rare Species")
    color = "purple"

    # Assign color based on species name
    if species_name in species_colors:
    color = species_colors[species_name]
    elif "dolphin" in species_name.lower() or "porpoise" in species_name.lower():
    color = "blue"
    elif "turtle" in species_name.lower():
    color = "darkgreen"

    # Create symbol
    symbol = QgsSymbol.defaultSymbol(layer.geometryType())
    symbol.setColor(QColor(color))

    # Create category using speciesID
    category = QgsRendererCategory(species_id, symbol, species_name)
    categories.append(category)

    # Apply color renderer based on speciesID field
    renderer = QgsCategorizedSymbolRenderer("speciesID", categories)
    layer.setRenderer(renderer)
    layer.triggerRepaint()

    #```

  4. Click the green Run Script button.

  5. Data should now be displayed in QGIS as points on the map.

Be Aware: Submitting a large query to the API via QGIS may lead to your system crashing given the large amount of data points. Recommended to save work before querying, and ensure that the DATEFROM and DATETO variables are assigned to a period you are interested in. The smaller the period, the faster the query.

Adding a Basemap

To see the points overlayed with context, you will need to add a basemap:

  1. Go to Plugins → Manage and Install Plugins.

  2. Search for QuickMapServices and install it.

  3. Once installed, go to Web ► QuickMapServices ► OSM ► OSM Standard (or choose another basemap like Google Satellite / OpenStreetMap Standard.).

  4. The basemap will now appear beneath your whale sightings layer.

Applying Filters in QGIS

Now your data is in QGIS, you may want to filter the data by species or other parameters (e.g., only showing Killer Whales):

  1. Open the Attribute Table

    1. Right-click on layer Open Attribute Table.

  2. Click on Select by Expression.

  3. Use the following expression:

  4. Click Select Features to highlight those records.

  5. To create a new layer with only the filtered features, go to Layer ► Export ► Save Selected Features As…

Filter by Drawing an Area

To filter by area:

  1. Activate the Select Features by Polygon tool.

  2. Draw an area around the sightings you want to filter.

  3. Click Filter Selected Features to keep only the selected points.

Resources

More information on how to use QGIS features can be found online, these resources will get you started:

Did this answer your question?