0
# Notes Operations
1
2
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.
3
4
## Capabilities
5
6
### Notes Retrieval by Area
7
8
Get notes within a specified bounding box with filtering options.
9
10
```python { .api }
11
def NotesGet(min_lon, min_lat, max_lon, max_lat, limit=100, closed=7):
12
"""
13
Returns a list of notes in the specified bounding box.
14
15
Parameters:
16
- min_lon (float): Western boundary
17
- min_lat (float): Southern boundary
18
- max_lon (float): Eastern boundary
19
- max_lat (float): Northern boundary
20
- limit (int, optional): Maximum number of results (default: 100)
21
- closed (int, optional): Days closed notes remain visible (default: 7)
22
0 = only open notes, -1 = all notes
23
24
Returns:
25
list[dict]: List of note dictionaries with id, coordinates, status,
26
dates, user info, and comments
27
"""
28
```
29
30
**Usage Example:**
31
32
```python
33
import osmapi
34
35
api = osmapi.OsmApi()
36
37
# Get notes in downtown Seattle area
38
notes = api.NotesGet(
39
min_lon=-122.35,
40
min_lat=47.60,
41
max_lon=-122.30,
42
max_lat=47.63,
43
limit=50,
44
closed=14 # Include notes closed in last 14 days
45
)
46
47
print(f"Found {len(notes)} notes in the area:")
48
for note in notes:
49
status_icon = "🟢" if note['status'] == 'open' else "🔴"
50
print(f"{status_icon} Note {note['id']}: {note['status']}")
51
print(f" Location: ({note['lat']}, {note['lon']})")
52
print(f" Created: {note['date_created']}")
53
54
# Show first comment (original note text)
55
if note['comments']:
56
first_comment = note['comments'][0]
57
print(f" Text: {first_comment['text'][:100]}...")
58
```
59
60
### Individual Note Retrieval
61
62
Get detailed information about a specific note.
63
64
```python { .api }
65
def NoteGet(id):
66
"""
67
Returns a note as dict.
68
69
Parameters:
70
- id (int): Unique identifier of the note
71
72
Returns:
73
dict: Note data including id, coordinates, status, dates,
74
user info, and complete comment thread
75
"""
76
```
77
78
**Usage Example:**
79
80
```python
81
import osmapi
82
83
api = osmapi.OsmApi()
84
85
# Get specific note with full details
86
note = api.NoteGet(12345)
87
88
print(f"Note {note['id']}: {note['status']}")
89
print(f"Location: ({note['lat']}, {note['lon']})")
90
print(f"Created: {note['date_created']}")
91
92
if note['date_closed']:
93
print(f"Closed: {note['date_closed']}")
94
95
print(f"\nComment thread ({len(note['comments'])} comments):")
96
for i, comment in enumerate(note['comments']):
97
user = comment['user'] or "Anonymous"
98
action_text = {
99
'opened': 'opened this note',
100
'commented': 'commented',
101
'closed': 'closed this note'
102
}.get(comment['action'], comment['action'])
103
104
print(f"{i+1}. {user} {action_text} on {comment['date']}")
105
print(f" {comment['text']}")
106
```
107
108
### Note Creation
109
110
Create new notes to report issues or suggest improvements.
111
112
```python { .api }
113
def NoteCreate(NoteData):
114
"""
115
Creates a note based on the supplied NoteData dict.
116
117
Parameters:
118
- NoteData (dict): Note data with coordinates and text
119
Required: lat (float), lon (float), text (str)
120
121
Returns:
122
dict: Complete note data including assigned id, status, dates,
123
and initial comment
124
"""
125
```
126
127
**Usage Example:**
128
129
```python
130
import osmapi
131
132
api = osmapi.OsmApi()
133
134
# Create a new note (no authentication required)
135
new_note = api.NoteCreate({
136
"lat": 47.6062,
137
"lon": -122.3321,
138
"text": "This intersection needs a traffic light. Heavy pedestrian traffic from the nearby school makes crossing dangerous during rush hours."
139
})
140
141
print(f"Created note {new_note['id']}")
142
print(f"Status: {new_note['status']}")
143
print(f"Location: ({new_note['lat']}, {new_note['lon']})")
144
print(f"Created: {new_note['date_created']}")
145
146
# The text becomes the first comment
147
first_comment = new_note['comments'][0]
148
print(f"Initial comment: {first_comment['text']}")
149
```
150
151
### Note Commenting
152
153
Add comments to existing notes to provide additional information or updates.
154
155
```python { .api }
156
def NoteComment(NoteId, comment):
157
"""
158
Adds a new comment to a note.
159
160
Parameters:
161
- NoteId (int): ID of the note to comment on
162
- comment (str): Comment text
163
164
Returns:
165
dict: Updated note data with new comment added
166
"""
167
```
168
169
**Usage Example:**
170
171
```python
172
import osmapi
173
174
api = osmapi.OsmApi()
175
176
note_id = 12345
177
178
# Add a comment (no authentication required)
179
updated_note = api.NoteComment(
180
note_id,
181
"I've contacted the city traffic department about this intersection. They've added it to their review queue for next quarter."
182
)
183
184
print(f"Added comment to note {note_id}")
185
print(f"Note now has {len(updated_note['comments'])} comments")
186
187
# Show the new comment
188
latest_comment = updated_note['comments'][-1]
189
print(f"Latest comment by {latest_comment['user'] or 'Anonymous'}:")
190
print(f" {latest_comment['text']}")
191
```
192
193
### Note Status Management
194
195
Close or reopen notes based on resolution status.
196
197
```python { .api }
198
def NoteClose(NoteId, comment):
199
"""
200
Closes a note.
201
202
Parameters:
203
- NoteId (int): ID of the note to close
204
- comment (str): Closing comment explaining resolution
205
206
Returns:
207
dict: Updated note data with closed status
208
209
Raises:
210
- UsernamePasswordMissingError: If no authentication provided
211
"""
212
213
def NoteReopen(NoteId, comment):
214
"""
215
Reopens a closed note.
216
217
Parameters:
218
- NoteId (int): ID of the note to reopen
219
- comment (str): Comment explaining why note is reopened
220
221
Returns:
222
dict: Updated note data with open status
223
224
Raises:
225
- UsernamePasswordMissingError: If no authentication provided
226
- ElementDeletedApiError: If note was deleted
227
- ElementNotFoundApiError: If note cannot be found
228
"""
229
```
230
231
**Usage Example:**
232
233
```python
234
import osmapi
235
236
# Authentication required for closing/reopening notes
237
api = osmapi.OsmApi(username="your_username", password="your_password")
238
239
note_id = 12345
240
241
# Close a note when issue is resolved
242
closed_note = api.NoteClose(
243
note_id,
244
"Traffic light has been installed at this intersection. Issue resolved."
245
)
246
247
print(f"Closed note {note_id}")
248
print(f"Status: {closed_note['status']}")
249
print(f"Closed date: {closed_note['date_closed']}")
250
251
# Reopen if issue returns or closure was premature
252
if closed_note['status'] == 'closed':
253
reopened_note = api.NoteReopen(
254
note_id,
255
"Traffic light was removed during road construction. Issue has returned."
256
)
257
258
print(f"Reopened note {note_id}")
259
print(f"Status: {reopened_note['status']}")
260
```
261
262
### Note Search
263
264
Search for notes by text content.
265
266
```python { .api }
267
def NotesSearch(query, limit=100, closed=7):
268
"""
269
Returns a list of notes that match the given search query.
270
271
Parameters:
272
- query (str): Search query text
273
- limit (int, optional): Maximum number of results (default: 100)
274
- closed (int, optional): Days closed notes remain searchable (default: 7)
275
0 = only open notes, -1 = all notes
276
277
Returns:
278
list[dict]: List of note dictionaries matching the search criteria
279
"""
280
```
281
282
**Usage Example:**
283
284
```python
285
import osmapi
286
287
api = osmapi.OsmApi()
288
289
# Search for notes about traffic lights
290
traffic_notes = api.NotesSearch(
291
query="traffic light",
292
limit=25,
293
closed=30 # Include notes closed in last 30 days
294
)
295
296
print(f"Found {len(traffic_notes)} notes about traffic lights:")
297
for note in traffic_notes:
298
print(f"Note {note['id']} ({note['status']})")
299
print(f" Location: ({note['lat']:.4f}, {note['lon']:.4f})")
300
301
# Show matching text from comments
302
for comment in note['comments']:
303
if 'traffic light' in comment['text'].lower():
304
text_snippet = comment['text'][:100]
305
print(f" Match: {text_snippet}...")
306
break
307
308
# Search for notes about specific amenities
309
shop_notes = api.NotesSearch("shop closed permanently", limit=10)
310
print(f"\nFound {len(shop_notes)} notes about permanently closed shops")
311
```
312
313
## Note Data Structure
314
315
### Note Dictionary
316
317
```python { .api }
318
NoteData = {
319
'id': int, # Note ID (assigned by OSM)
320
'lat': float, # Latitude in decimal degrees
321
'lon': float, # Longitude in decimal degrees
322
'status': str, # 'open' or 'closed'
323
'date_created': str, # ISO timestamp of creation
324
'date_closed': str, # ISO timestamp of closure (or None)
325
'uid': int, # User ID of creator (or None for anonymous)
326
'user': str, # Username of creator (or None for anonymous)
327
'comments': list[dict] # List of comment objects
328
}
329
330
NoteComment = {
331
'date': str, # ISO timestamp of comment
332
'action': str, # 'opened', 'commented', or 'closed'
333
'text': str, # Comment text content
334
'html': str, # HTML version of comment (with links)
335
'uid': int, # User ID of commenter (or None)
336
'user': str # Username of commenter (or None)
337
}
338
```
339
340
## Note Use Cases and Examples
341
342
### Issue Reporting
343
344
```python
345
import osmapi
346
347
api = osmapi.OsmApi()
348
349
# Report a mapping error
350
api.NoteCreate({
351
"lat": 47.6205,
352
"lon": -122.3493,
353
"text": "This building is labeled as 'City Hall' but it's actually a library. The real City Hall is two blocks south."
354
})
355
356
# Report missing information
357
api.NoteCreate({
358
"lat": 47.6097,
359
"lon": -122.3331,
360
"text": "New restaurant opened here: 'Pasta Palace'. Italian cuisine, opens 11 AM - 10 PM daily."
361
})
362
```
363
364
### Community Collaboration
365
366
```python
367
import osmapi
368
369
api = osmapi.OsmApi()
370
371
# Follow up on existing notes
372
note_id = 54321
373
api.NoteComment(
374
note_id,
375
"I can confirm this business has moved. The new location is at 456 Oak Street. Should we update the map?"
376
)
377
378
# Provide additional context
379
api.NoteComment(
380
note_id,
381
"According to the business website, they moved on March 15th. The old location is now vacant."
382
)
383
```
384
385
### Data Quality Monitoring
386
387
```python
388
import osmapi
389
390
api = osmapi.OsmApi()
391
392
# Search for validation-related notes
393
validation_notes = api.NotesSearch("validation error", limit=50, closed=-1)
394
395
print("Data quality issues found:")
396
for note in validation_notes:
397
# Analyze note patterns
398
age_days = (datetime.now() - note['date_created']).days
399
print(f"Note {note['id']}: {age_days} days old, {note['status']}")
400
401
# Check if issue was addressed
402
if note['status'] == 'closed':
403
resolution_time = (note['date_closed'] - note['date_created']).days
404
print(f" Resolved in {resolution_time} days")
405
```
406
407
## Note Management Best Practices
408
409
### Creating Effective Notes
410
- Be specific about the location and issue
411
- Provide clear, actionable information
412
- Include relevant details (business hours, contact info)
413
- Use descriptive language for better searchability
414
415
### Following Up on Notes
416
- Check existing notes before creating duplicates
417
- Add helpful information when you have local knowledge
418
- Close notes when issues are genuinely resolved
419
- Provide closure comments explaining the resolution
420
421
### Community Interaction
422
- Be respectful and constructive in comments
423
- Acknowledge others' contributions
424
- Provide updates when circumstances change
425
- Use notes for collaboration, not arguments
426
427
## Error Handling
428
429
Notes operations can raise exceptions in certain scenarios:
430
431
```python
432
import osmapi
433
434
api = osmapi.OsmApi()
435
436
try:
437
note = api.NoteGet(999999)
438
except osmapi.ElementNotFoundApiError:
439
print("Note does not exist")
440
441
# Authentication required for closing/reopening
442
try:
443
api.NoteClose(12345, "Issue resolved")
444
except osmapi.UsernamePasswordMissingError:
445
print("Authentication required to close notes")
446
447
try:
448
api.NoteReopen(12345, "Issue returned")
449
except osmapi.ElementDeletedApiError:
450
print("Note has been deleted")
451
except osmapi.NoteAlreadyClosedApiError:
452
print("Note is already closed")
453
```
454
455
## Geographic and Temporal Filtering
456
457
### Bounding Box Best Practices
458
- Use reasonable area sizes to avoid overwhelming results
459
- Consider population density when setting limits
460
- Filter by closure date to focus on recent activity
461
462
### Search Optimization
463
- Use specific keywords for better results
464
- Combine location filtering with text search when possible
465
- Consider different languages and terminology variations
466
467
```python
468
import osmapi
469
470
api = osmapi.OsmApi()
471
472
# Focused area search with temporal filtering
473
recent_notes = api.NotesGet(
474
min_lon=-122.32,
475
min_lat=47.61,
476
max_lon=-122.31,
477
max_lat=47.62,
478
limit=20,
479
closed=3 # Only notes closed in last 3 days
480
)
481
482
# Multi-language search for international areas
483
multilingual_search_terms = ["shop closed", "magasin fermé", "tienda cerrada"]
484
all_closure_notes = []
485
486
for term in multilingual_search_terms:
487
notes = api.NotesSearch(term, limit=25)
488
all_closure_notes.extend(notes)
489
490
# Remove duplicates based on note ID
491
unique_notes = {note['id']: note for note in all_closure_notes}
492
print(f"Found {len(unique_notes)} unique notes about closures")
493
```