Events API
Complete documentation for the VOTR Events API endpoint
📅 Events Retrieval
The Events API allows you to retrieve voting events filtered by record date or using cursor-based pagination. This endpoint provides access to event information including event IDs, record dates, CUSIP numbers, and issuer details.
API Endpoints
Development:
GET https://api-dev.govotr.com/api/v1/events
Production:
GET https://api.govotr.com/api/v1/events
Authentication
This endpoint uses the same OAuth authentication flow as other VOTR APIs.
Headers
Authorization: Bearer YOUR_ACCESS_TOKEN
Content-Type: application/json
📋 For OAuth token generation, refer to: OAuth Token Documentation
Query Parameters
Parameter Requirements
| Parameter | Type | Required | Description |
|---|---|---|---|
date |
string |
✅ | Record date to filter events (YYYY-MM-DD format, ET timezone) |
cursor |
string |
❌ | Cursor for pagination (ObjectId of last event) |
limit |
integer |
❌ | Maximum events per page (default: 50, max: 100) |
Important: The
dateparameter is required for all requests. If thedateparameter is not provided, the API will return a 400 Bad Request error. Usecursoralong withdatefor pagination.
Parameter Details
Date Parameter
- Format: YYYY-MM-DD (ISO 8601 date format, ET timezone)
- Timezone: ET (Eastern Time)
- Purpose: Fetch events for a specific record date
- Required: Yes, must be provided in all requests
- Example:
2024-01-15(ET timezone)
Cursor Parameter
- Format: 24-character hexadecimal ObjectId
- Purpose: Fetch the next page of events using pagination
- Required: No, use only for pagination with the
dateparameter - Example:
64f8a1b2c3d4e5f6a7b8c9d0
Limit Parameter
- Type: Integer
- Default: 50
- Maximum: 100
- Purpose: Control number of events returned per page
Pagination
Important: The
dateparameter is required for all requests.
- First request: Pass the
dateparameter (e.g.,?date=2024-01-15)- To fetch next page: Pass both
dateANDcursorparameters together (e.g.,?date=2024-01-15&cursor=64f8a1b2c3d4e5f6a7b8c9d0)- Use the
nextCursorvalue from the pagination response to fetch the next page- Continue until
hasMoreisfalseto retrieve all events for the specified date
Response Format
Success Response
{
"message": "Events retrieved successfully",
"status": true,
"data": {
"events": [
{
"eventId": "64f8a1b2c3d4e5f6a7b8c9d0",
"recordDate": "2024-01-15",
"cusip": ["123456789", "987654321"],
"isin": ["US1234567890", "US0987654321"],
"ticker": ["AAPL", "MSFT"],
"issuerName": "Apple Inc.",
"eventType": "Proxy"
}
],
"pagination": {
"hasMore": true,
"nextCursor": "64f8a1b2c3d4e5f6a7b8c9d1",
"limit": 50
}
}
}
Response Schema
Main Response Object
| Field | Type | Description |
|---|---|---|
message |
string |
Success message |
status |
boolean |
Request status (true for success) |
data |
object |
Response data containing events |
Data Object
| Field | Type | Description |
|---|---|---|
events |
array |
Array of event objects |
pagination |
object |
Pagination metadata |
Event Object
| Field | Type | Description |
|---|---|---|
eventId |
string |
Unique event identifier (ObjectId) |
recordDate |
string |
Event record date (YYYY-MM-DD, ET timezone) |
cusip |
array |
Array of CUSIP numbers |
isin |
array |
Array of ISIN (International Securities Identification Number) for matching child issuers |
ticker |
array |
Array of ticker symbols for matching child issuers |
issuerName |
string |
Name of the issuing company |
eventType |
string |
Type of voting event (see Event Types below) |
Pagination Object
| Field | Type | Description |
|---|---|---|
hasMore |
boolean |
Whether more events are available |
nextCursor |
string |
Cursor for next page (if hasMore=true) |
limit |
integer |
Current page limit |
Event Types
The eventType field can contain one of the following values:
- Proxy
- Regulatory
- Voluntary Corporate Actions
Empty Data Response
When there are no events for the requested date or cursor, the API returns:
{
"message": "Events retrieved successfully",
"status": true,
"data": {
"events": [],
"pagination": {
"hasMore": false,
"nextCursor": null,
"limit": 50
}
}
}
Usage Examples
Get Events by Date (First Request)
curl -X GET "https://api-dev.govotr.com/api/v1/events?date=2024-01-15&limit=50" \
-H "Authorization: Bearer YOUR_ACCESS_TOKEN" \
-H "Content-Type: application/json"
Get Next Page Using Cursor and Date (Subsequent Requests)
curl -X GET "https://api-dev.govotr.com/api/v1/events?date=2024-01-15&cursor=64f8a1b2c3d4e5f6a7b8c9d0&limit=50" \
-H "Authorization: Bearer YOUR_ACCESS_TOKEN" \
-H "Content-Type: application/json"
Note: When paginating through events for a specific date, always include both the
dateandcursorparameters in subsequent requests to ensure you’re getting the next page of events for that same date.
JavaScript/Node.js Example
// Get events by date (first request)
async function getEventsByDate(accessToken, date, limit = 50) {
try {
const response = await fetch(
`https://api-dev.govotr.com/api/v1/events?date=${date}&limit=${limit}`,
{
method: "GET",
headers: {
Authorization: `Bearer ${accessToken}`,
"Content-Type": "application/json",
},
}
)
const data = await response.json()
if (data.status) {
console.log("Events retrieved successfully:", data.data.events)
return data.data
} else {
console.error("Error retrieving events:", data.message)
return null
}
} catch (error) {
console.error("Network error:", error)
return null
}
}
// Get next page using cursor and date (subsequent requests)
async function getEventsByDateAndCursor(accessToken, date, cursor, limit = 50) {
try {
const response = await fetch(
`https://api-dev.govotr.com/api/v1/events?date=${date}&cursor=${cursor}&limit=${limit}`,
{
method: "GET",
headers: {
Authorization: `Bearer ${accessToken}`,
"Content-Type": "application/json",
},
}
)
const data = await response.json()
if (data.status) {
console.log("Events retrieved successfully:", data.data.events)
return data.data
} else {
console.error("Error retrieving events:", data.message)
return null
}
} catch (error) {
console.error("Network error:", error)
return null
}
}
// Usage example
const accessToken = "your_access_token_here"
const date = "2024-01-15"
// First request
getEventsByDate(accessToken, date, 50)
// Subsequent requests with cursor
// getEventsByDateAndCursor(accessToken, date, "64f8a1b2c3d4e5f6a7b8c9d0", 50)
Python Example
import requests
from datetime import datetime
def get_events_by_date(access_token, date, limit=50):
"""
Retrieve events for a specific record date
"""
url = "https://api-dev.govotr.com/api/v1/events"
headers = {
"Authorization": f"Bearer {access_token}",
"Content-Type": "application/json"
}
params = {
"date": date,
"limit": limit
}
try:
response = requests.get(url, headers=headers, params=params)
if response.status_code == 200:
data = response.json()
if data.get("status"):
print(f"Events retrieved successfully: {len(data['data']['events'])} events")
return data["data"]
else:
print(f"Error: {data.get('message', 'Unknown error')}")
return None
else:
print(f"HTTP Error: {response.status_code}")
print(response.text)
return None
except requests.exceptions.RequestException as e:
print(f"Network error: {e}")
return None
def get_events_by_date_and_cursor(access_token, date, cursor, limit=50):
"""
Retrieve events using cursor pagination for a specific date
"""
url = "https://api-dev.govotr.com/api/v1/events"
headers = {
"Authorization": f"Bearer {access_token}",
"Content-Type": "application/json"
}
params = {
"date": date,
"cursor": cursor,
"limit": limit
}
try:
response = requests.get(url, headers=headers, params=params)
if response.status_code == 200:
data = response.json()
if data.get("status"):
print(f"Events retrieved successfully: {len(data['data']['events'])} events")
return data["data"]
else:
print(f"Error: {data.get('message', 'Unknown error')}")
return None
else:
print(f"HTTP Error: {response.status_code}")
print(response.text)
return None
except requests.exceptions.RequestException as e:
print(f"Network error: {e}")
return None
# Usage example
access_token = "your_access_token_here"
date = "2024-01-15"
# First request
events_data = get_events_by_date(access_token, date, 50)
# Subsequent requests with cursor
# next_data = get_events_by_date_and_cursor(access_token, date, "64f8a1b2c3d4e5f6a7b8c9d0", 50)
Error Handling
Common Error Responses
400 - Bad Request
Invalid date format:
{
"status": false,
"error": "Invalid date format. Use YYYY-MM-DD format"
}
Invalid parameter combination (when not paginating correctly):
{
"status": false,
"error": "Invalid parameter combination"
}
Note: You can use
dateandcursortogether for pagination. This error occurs when parameters are used incorrectly.
401 - Unauthorized
Invalid or missing OAuth token:
{
"status": false,
"error": "Authorization header is required"
}
429 - Rate Limited
Too many requests:
{
"status": false,
"error": "Rate limit exceeded. Please try again later"
}
500 - Internal Server Error
Missing required date parameter:
{
"status": false,
"error": "Date parameter is required"
}
Server error:
{
"status": false,
"error": "Internal server error"
}
Features
Rate Limiting
- Protection: Prevents API abuse
- Scope: Applied per access token
- Response: HTTP 429 when limit exceeded
Best Practices
Performance
- Use appropriate limits - Don’t request more events than needed
- Handle pagination efficiently - Process events in batches rather than loading all at once
Error Handling
- Check response status - Always verify the
statusfield before processing data - Implement retry logic - Handle rate limiting with exponential backoff
- Log errors appropriately - Monitor API usage and error patterns
Security
- Secure token storage - Store OAuth tokens securely
- Token refresh - Implement token refresh logic for long-running applications
- Environment separation - Use development endpoints for testing
Data Processing
- Validate event data - Check required fields before processing
- Handle empty results - Account for dates with no events
- Process CUSIP arrays - Remember that CUSIP is an array field
Next Steps:
- Check event voting status and availability: Event Voting Status API
- Use the retrieved event information with the Voting URL API to generate voting URLs for specific events and shareholders
Get the current voting status and availability information for a specific event. This endpoint allows brokers to check whether voting is currently active and available for an event.
Note: This endpoint is optional and not required for basic voting functionality. Use it to provide enhanced UI experience by checking voting availability before presenting options to shareholders.
API Endpoints
Development:
GET https://api-dev.govotr.com/api/v1/event/{eventId}
Production:
GET https://api.govotr.com/api/v1/event/{eventId}
Authentication
This endpoint uses the same OAuth authentication flow as other VOTR APIs.
Headers
Authorization: Bearer YOUR_ACCESS_TOKEN
Content-Type: application/json
Path Parameters
| Parameter | Type | Required | Description |
|---|---|---|---|
eventId |
string |
✅ | Unique identifier for the event (ObjectId) |
Parameter Details
Event ID Parameter
- Format: 24-character hexadecimal MongoDB ObjectId
- Pattern:
^[0-9a-fA-F]{24}$ - Required: Yes
- Example:
64f8a1b2c3d4e5f6a7b8c9d0
Query Parameters
| Parameter | Type | Required | Description |
|---|---|---|---|
cusip |
string |
❌ | Optional CUSIP number to filter by specific security |
Parameter Details
CUSIP Parameter
- Format: String
- Required: No
- Purpose: Filter the event by specific security CUSIP
- Example:
037833100
Use Cases
- Check Voting Availability: Determine if voting links are currently active
- Event Status Verification: Get current event status (Active, Upcoming, Expired, Cancelled)
- Timeline Information: Retrieve voting open date/time and deadline
- UI Enhancement: Verify event details before presenting to shareholders
- Status Polling: Monitor when voting becomes available
Event Status Values
| Status | Description |
|---|---|
Active |
Event is currently accepting votes |
Upcoming |
Event has not started yet (status = 1) |
Expired |
Voting period has ended (status = 3) |
Cancelled |
Event has been cancelled (status = 5) |
Voting Links Active
The votingLinksActive field indicates whether shareholders can currently vote:
true: Voting is open and links are functionalfalse: Voting is not available (event not started, ended, or cancelled)
Conditions for Active Voting Links:
- Final documents are confirmed (
confirmFinalDocuments = true) - Event status is Active (
status = 2) - Current time is before the voting deadline
Response Caching
Responses are cached with dynamic TTL for optimal performance:
| Event State | Cache Duration |
|---|---|
| Active Events | Cached until voting ends (minimum 60 seconds) |
| Expired/Cancelled | Cached for 24 hours |
| Default | 1 hour |
Cache Auto-Clear Triggers:
- Event details are updated
- Event status changes
- Ballots are modified
- Mailing status is updated
Response Format
Success Response
{
"message": "Event voting status retrieved successfully",
"status": true,
"data": {
"eventId": "64f8a1b2c3d4e5f6a7b8c9d0",
"cusip": "037833100",
"recordDate": "2024-01-15",
"meetingDate": "2024-02-15",
"meetingTime": "10:00 AM",
"votingOpenDateTime": "2024-01-16T09:00:00.000Z",
"votingDeadline": "2024-02-14T23:59:59.000Z",
"eventStatus": "Active",
"votingLinksActive": true
}
}
Response Schema
Main Response Object
| Field | Type | Description |
|---|---|---|
message |
string |
Success message |
status |
boolean |
Request status (true for success) |
data |
object |
Event voting status data |
Data Object
| Field | Type | Description |
|---|---|---|
eventId |
string |
Unique identifier for the event |
cusip |
string |
CUSIP number (if provided in request), nullable |
recordDate |
string |
Record date (YYYY-MM-DD, ET timezone), nullable |
meetingDate |
string |
Meeting date (YYYY-MM-DD, ET timezone), nullable |
meetingTime |
string |
Meeting time (ET timezone), nullable |
votingOpenDateTime |
string |
ISO 8601 timestamp when voting became available (when first email was delivered). Null if no emails delivered. |
votingDeadline |
string |
ISO 8601 timestamp for voting end date and time |
eventStatus |
string |
Current event status (Active, Upcoming, Expired, Cancelled) |
votingLinksActive |
boolean |
Whether voting links are currently active and functional |
Usage Examples
Get Event Voting Status by Event ID
curl -X GET "https://api-dev.govotr.com/api/v1/event/64f8a1b2c3d4e5f6a7b8c9d0" \
-H "Authorization: Bearer YOUR_ACCESS_TOKEN" \
-H "Content-Type: application/json"
Get Event Voting Status with CUSIP Filter
curl -X GET "https://api-dev.govotr.com/api/v1/event/64f8a1b2c3d4e5f6a7b8c9d0?cusip=037833100" \
-H "Authorization: Bearer YOUR_ACCESS_TOKEN" \
-H "Content-Type: application/json"
JavaScript/Node.js Example
async function getEventVotingStatus(accessToken, eventId, cusip = null) {
try {
const url = new URL(`https://api-dev.govotr.com/api/v1/event/${eventId}`)
if (cusip) {
url.searchParams.append("cusip", cusip)
}
const response = await fetch(url.toString(), {
method: "GET",
headers: {
Authorization: `Bearer ${accessToken}`,
"Content-Type": "application/json",
},
})
const data = await response.json()
if (data.status) {
console.log("Event voting status:", data.data)
// Check if voting is available
if (data.data.votingLinksActive) {
console.log("✅ Voting is currently active!")
console.log(`Voting deadline: ${data.data.votingDeadline}`)
} else {
console.log(
`❌ Voting not available. Event status: ${data.data.eventStatus}`
)
}
return data.data
} else {
console.error("Error retrieving event status:", data.error)
return null
}
} catch (error) {
console.error("Network error:", error)
return null
}
}
// Usage examples
const accessToken = "your_access_token_here"
const eventId = "64f8a1b2c3d4e5f6a7b8c9d0"
// Get event status
getEventVotingStatus(accessToken, eventId)
// Get event status with CUSIP filter
getEventVotingStatus(accessToken, eventId, "037833100")
Python Example
import requests
from datetime import datetime
def get_event_voting_status(access_token, event_id, cusip=None):
"""
Retrieve voting status for a specific event
"""
url = f"https://api-dev.govotr.com/api/v1/event/{event_id}"
headers = {
"Authorization": f"Bearer {access_token}",
"Content-Type": "application/json"
}
params = {}
if cusip:
params["cusip"] = cusip
try:
response = requests.get(url, headers=headers, params=params)
if response.status_code == 200:
data = response.json()
if data.get("status"):
event_data = data["data"]
print(f"Event Status: {event_data['eventStatus']}")
if event_data["votingLinksActive"]:
print("✅ Voting is currently active!")
print(f"Voting deadline: {event_data['votingDeadline']}")
else:
print(f"❌ Voting not available. Status: {event_data['eventStatus']}")
return event_data
else:
print(f"Error: {data.get('error', 'Unknown error')}")
return None
elif response.status_code == 404:
print(f"Event not found: {event_id}")
return None
else:
print(f"HTTP Error: {response.status_code}")
print(response.text)
return None
except requests.exceptions.RequestException as e:
print(f"Network error: {e}")
return None
# Usage examples
access_token = "your_access_token_here"
event_id = "64f8a1b2c3d4e5f6a7b8c9d0"
# Get event status
event_status = get_event_voting_status(access_token, event_id)
# Get event status with CUSIP filter
event_status_with_cusip = get_event_voting_status(access_token, event_id, "037833100")
Error Handling
Common Error Responses
400 - Bad Request
Invalid Event ID format:
{
"status": false,
"error": "Event ID must be a valid ObjectId"
}
Missing Event ID:
{
"status": false,
"error": "Event ID is required"
}
Invalid CUSIP type:
{
"status": false,
"error": "CUSIP must be a string"
}
401 - Unauthorized
Invalid or missing OAuth token:
{
"status": false,
"error": "Authorization header is required"
}
404 - Not Found
Event not found:
{
"status": false,
"error": "Event not found for the provided Event ID"
}
Event not found with CUSIP:
{
"status": false,
"error": "Event not found for the provided Event ID and CUSIP"
}
500 - Internal Server Error
Server error:
{
"status": false,
"error": "Internal server error"
}
Best Practices
Polling Strategy
- Check before presenting UI: Verify voting is active before showing “Vote Now” button
- Implement smart polling: Poll more frequently as voting deadline approaches
- Cache responses: Leverage the built-in caching mechanism
- Handle status transitions: Update UI when event status changes
Error Handling
- Validate Event ID format: Ensure Event ID matches ObjectId pattern before API call
- Handle 404 gracefully: Event may not exist or may be filtered out by CUSIP
- Implement retry logic: Handle transient failures with exponential backoff
- Log errors appropriately: Monitor API usage and error patterns
Performance
- Use caching: Respect cache headers to reduce unnecessary API calls
- Batch checks: If checking multiple events, space out requests appropriately
- Monitor response times: Track API performance for your use case
UI/UX
- Display event status: Show clear status indicators (Active, Upcoming, Expired)
- Show voting timeline: Display voting open date/time and deadline to users
- Disable when inactive: Disable “Vote Now” button when
votingLinksActiveis false - Provide context: Explain why voting is not available (upcoming, expired, cancelled)
Next Steps: Use the retrieved event information with the Voting URL API to generate voting URLs for specific events and shareholders.