CtrlK
BlogDocsLog inGet started
Tessl Logo

tessl/pypi-osmapi

Python wrapper for the OSM API

Pending
Overview
Eval results
Files

notes.mddocs/

Notes Operations

Full Notes API support including creation, commenting, status management, and search functionality. Notes enable community interaction and issue reporting for OpenStreetMap, allowing users to highlight problems, suggest improvements, and collaborate on data quality.

Capabilities

Notes Retrieval by Area

Get notes within a specified bounding box with filtering options.

def NotesGet(min_lon, min_lat, max_lon, max_lat, limit=100, closed=7):
    """
    Returns a list of notes in the specified bounding box.
    
    Parameters:
    - min_lon (float): Western boundary
    - min_lat (float): Southern boundary  
    - max_lon (float): Eastern boundary
    - max_lat (float): Northern boundary
    - limit (int, optional): Maximum number of results (default: 100)
    - closed (int, optional): Days closed notes remain visible (default: 7)
                              0 = only open notes, -1 = all notes
    
    Returns:
    list[dict]: List of note dictionaries with id, coordinates, status,
                dates, user info, and comments
    """

Usage Example:

import osmapi

api = osmapi.OsmApi()

# Get notes in downtown Seattle area
notes = api.NotesGet(
    min_lon=-122.35,
    min_lat=47.60,
    max_lon=-122.30,
    max_lat=47.63,
    limit=50,
    closed=14  # Include notes closed in last 14 days
)

print(f"Found {len(notes)} notes in the area:")
for note in notes:
    status_icon = "🟢" if note['status'] == 'open' else "🔴"
    print(f"{status_icon} Note {note['id']}: {note['status']}")
    print(f"   Location: ({note['lat']}, {note['lon']})")
    print(f"   Created: {note['date_created']}")
    
    # Show first comment (original note text)
    if note['comments']:
        first_comment = note['comments'][0]
        print(f"   Text: {first_comment['text'][:100]}...")

Individual Note Retrieval

Get detailed information about a specific note.

def NoteGet(id):
    """
    Returns a note as dict.
    
    Parameters:
    - id (int): Unique identifier of the note
    
    Returns:
    dict: Note data including id, coordinates, status, dates,
          user info, and complete comment thread
    """

Usage Example:

import osmapi

api = osmapi.OsmApi()

# Get specific note with full details
note = api.NoteGet(12345)

print(f"Note {note['id']}: {note['status']}")
print(f"Location: ({note['lat']}, {note['lon']})")
print(f"Created: {note['date_created']}")

if note['date_closed']:
    print(f"Closed: {note['date_closed']}")

print(f"\nComment thread ({len(note['comments'])} comments):")
for i, comment in enumerate(note['comments']):
    user = comment['user'] or "Anonymous"
    action_text = {
        'opened': 'opened this note',
        'commented': 'commented',
        'closed': 'closed this note'
    }.get(comment['action'], comment['action'])
    
    print(f"{i+1}. {user} {action_text} on {comment['date']}")
    print(f"   {comment['text']}")

Note Creation

Create new notes to report issues or suggest improvements.

def NoteCreate(NoteData):
    """
    Creates a note based on the supplied NoteData dict.
    
    Parameters:
    - NoteData (dict): Note data with coordinates and text
      Required: lat (float), lon (float), text (str)
    
    Returns:
    dict: Complete note data including assigned id, status, dates,
          and initial comment
    """

Usage Example:

import osmapi

api = osmapi.OsmApi()

# Create a new note (no authentication required)
new_note = api.NoteCreate({
    "lat": 47.6062,
    "lon": -122.3321,
    "text": "This intersection needs a traffic light. Heavy pedestrian traffic from the nearby school makes crossing dangerous during rush hours."
})

print(f"Created note {new_note['id']}")
print(f"Status: {new_note['status']}")
print(f"Location: ({new_note['lat']}, {new_note['lon']})")
print(f"Created: {new_note['date_created']}")

# The text becomes the first comment
first_comment = new_note['comments'][0]
print(f"Initial comment: {first_comment['text']}")

Note Commenting

Add comments to existing notes to provide additional information or updates.

def NoteComment(NoteId, comment):
    """
    Adds a new comment to a note.
    
    Parameters:
    - NoteId (int): ID of the note to comment on
    - comment (str): Comment text
    
    Returns:
    dict: Updated note data with new comment added
    """

Usage Example:

import osmapi

api = osmapi.OsmApi()

note_id = 12345

# Add a comment (no authentication required)
updated_note = api.NoteComment(
    note_id,
    "I've contacted the city traffic department about this intersection. They've added it to their review queue for next quarter."
)

print(f"Added comment to note {note_id}")
print(f"Note now has {len(updated_note['comments'])} comments")

# Show the new comment
latest_comment = updated_note['comments'][-1]
print(f"Latest comment by {latest_comment['user'] or 'Anonymous'}:")
print(f"  {latest_comment['text']}")

Note Status Management

Close or reopen notes based on resolution status.

def NoteClose(NoteId, comment):
    """
    Closes a note.
    
    Parameters:
    - NoteId (int): ID of the note to close
    - comment (str): Closing comment explaining resolution
    
    Returns:
    dict: Updated note data with closed status
    
    Raises:
    - UsernamePasswordMissingError: If no authentication provided
    """

def NoteReopen(NoteId, comment):
    """
    Reopens a closed note.
    
    Parameters:
    - NoteId (int): ID of the note to reopen
    - comment (str): Comment explaining why note is reopened
    
    Returns:
    dict: Updated note data with open status
    
    Raises:
    - UsernamePasswordMissingError: If no authentication provided
    - ElementDeletedApiError: If note was deleted
    - ElementNotFoundApiError: If note cannot be found
    """

Usage Example:

import osmapi

# Authentication required for closing/reopening notes
api = osmapi.OsmApi(username="your_username", password="your_password")

note_id = 12345

# Close a note when issue is resolved
closed_note = api.NoteClose(
    note_id,
    "Traffic light has been installed at this intersection. Issue resolved."
)

print(f"Closed note {note_id}")
print(f"Status: {closed_note['status']}")
print(f"Closed date: {closed_note['date_closed']}")

# Reopen if issue returns or closure was premature
if closed_note['status'] == 'closed':
    reopened_note = api.NoteReopen(
        note_id,
        "Traffic light was removed during road construction. Issue has returned."
    )
    
    print(f"Reopened note {note_id}")
    print(f"Status: {reopened_note['status']}")

Note Search

Search for notes by text content.

def NotesSearch(query, limit=100, closed=7):
    """
    Returns a list of notes that match the given search query.
    
    Parameters:
    - query (str): Search query text
    - limit (int, optional): Maximum number of results (default: 100)
    - closed (int, optional): Days closed notes remain searchable (default: 7)
                              0 = only open notes, -1 = all notes
    
    Returns:
    list[dict]: List of note dictionaries matching the search criteria
    """

Usage Example:

import osmapi

api = osmapi.OsmApi()

# Search for notes about traffic lights
traffic_notes = api.NotesSearch(
    query="traffic light",
    limit=25,
    closed=30  # Include notes closed in last 30 days
)

print(f"Found {len(traffic_notes)} notes about traffic lights:")
for note in traffic_notes:
    print(f"Note {note['id']} ({note['status']})")
    print(f"  Location: ({note['lat']:.4f}, {note['lon']:.4f})")
    
    # Show matching text from comments
    for comment in note['comments']:
        if 'traffic light' in comment['text'].lower():
            text_snippet = comment['text'][:100]
            print(f"  Match: {text_snippet}...")
            break

# Search for notes about specific amenities
shop_notes = api.NotesSearch("shop closed permanently", limit=10)
print(f"\nFound {len(shop_notes)} notes about permanently closed shops")

Note Data Structure

Note Dictionary

NoteData = {
    'id': int,              # Note ID (assigned by OSM)
    'lat': float,           # Latitude in decimal degrees
    'lon': float,           # Longitude in decimal degrees
    'status': str,          # 'open' or 'closed'
    'date_created': str,    # ISO timestamp of creation
    'date_closed': str,     # ISO timestamp of closure (or None)
    'uid': int,             # User ID of creator (or None for anonymous)  
    'user': str,            # Username of creator (or None for anonymous)
    'comments': list[dict]  # List of comment objects
}

NoteComment = {
    'date': str,            # ISO timestamp of comment
    'action': str,          # 'opened', 'commented', or 'closed'
    'text': str,            # Comment text content
    'html': str,            # HTML version of comment (with links)
    'uid': int,             # User ID of commenter (or None)
    'user': str             # Username of commenter (or None)
}

Note Use Cases and Examples

Issue Reporting

import osmapi

api = osmapi.OsmApi()

# Report a mapping error
api.NoteCreate({
    "lat": 47.6205,
    "lon": -122.3493,
    "text": "This building is labeled as 'City Hall' but it's actually a library. The real City Hall is two blocks south."
})

# Report missing information
api.NoteCreate({
    "lat": 47.6097,
    "lon": -122.3331,
    "text": "New restaurant opened here: 'Pasta Palace'. Italian cuisine, opens 11 AM - 10 PM daily."
})

Community Collaboration

import osmapi

api = osmapi.OsmApi()

# Follow up on existing notes
note_id = 54321
api.NoteComment(
    note_id,
    "I can confirm this business has moved. The new location is at 456 Oak Street. Should we update the map?"
)

# Provide additional context
api.NoteComment(
    note_id,
    "According to the business website, they moved on March 15th. The old location is now vacant."
)

Data Quality Monitoring

import osmapi

api = osmapi.OsmApi()

# Search for validation-related notes
validation_notes = api.NotesSearch("validation error", limit=50, closed=-1)

print("Data quality issues found:")
for note in validation_notes:
    # Analyze note patterns
    age_days = (datetime.now() - note['date_created']).days
    print(f"Note {note['id']}: {age_days} days old, {note['status']}")
    
    # Check if issue was addressed
    if note['status'] == 'closed':
        resolution_time = (note['date_closed'] - note['date_created']).days
        print(f"  Resolved in {resolution_time} days")

Note Management Best Practices

Creating Effective Notes

  • Be specific about the location and issue
  • Provide clear, actionable information
  • Include relevant details (business hours, contact info)
  • Use descriptive language for better searchability

Following Up on Notes

  • Check existing notes before creating duplicates
  • Add helpful information when you have local knowledge
  • Close notes when issues are genuinely resolved
  • Provide closure comments explaining the resolution

Community Interaction

  • Be respectful and constructive in comments
  • Acknowledge others' contributions
  • Provide updates when circumstances change
  • Use notes for collaboration, not arguments

Error Handling

Notes operations can raise exceptions in certain scenarios:

import osmapi

api = osmapi.OsmApi()

try:
    note = api.NoteGet(999999)
except osmapi.ElementNotFoundApiError:
    print("Note does not exist")

# Authentication required for closing/reopening
try:
    api.NoteClose(12345, "Issue resolved")
except osmapi.UsernamePasswordMissingError:
    print("Authentication required to close notes")

try: 
    api.NoteReopen(12345, "Issue returned")
except osmapi.ElementDeletedApiError:
    print("Note has been deleted")
except osmapi.NoteAlreadyClosedApiError:
    print("Note is already closed")

Geographic and Temporal Filtering

Bounding Box Best Practices

  • Use reasonable area sizes to avoid overwhelming results
  • Consider population density when setting limits
  • Filter by closure date to focus on recent activity

Search Optimization

  • Use specific keywords for better results
  • Combine location filtering with text search when possible
  • Consider different languages and terminology variations
import osmapi

api = osmapi.OsmApi()

# Focused area search with temporal filtering
recent_notes = api.NotesGet(
    min_lon=-122.32,
    min_lat=47.61,
    max_lon=-122.31,
    max_lat=47.62,
    limit=20,
    closed=3  # Only notes closed in last 3 days
)

# Multi-language search for international areas
multilingual_search_terms = ["shop closed", "magasin fermé", "tienda cerrada"]
all_closure_notes = []

for term in multilingual_search_terms:
    notes = api.NotesSearch(term, limit=25)
    all_closure_notes.extend(notes)

# Remove duplicates based on note ID
unique_notes = {note['id']: note for note in all_closure_notes}
print(f"Found {len(unique_notes)} unique notes about closures")

Install with Tessl CLI

npx tessl i tessl/pypi-osmapi

docs

authentication.md

changesets.md

errors.md

index.md

nodes.md

notes.md

relations.md

ways.md

tile.json