How to Listen for Events
Warning: Beta software This API is in beta stage and may be subject to change. Therefore, we do not recommend using this in production.
Interested in this feature? Please reach out to mobility-services-developer@cisco.com
Overview
The event API allows you to subscribe to a variety of different events generated by Cisco's systems.
The examples will start a subscription to voice and voicemail events, which includes call initiated, call ended and new voicemail received.
Prerequisites
Required Scope
Event type | Required scope |
---|---|
CONSENT_REVOKE_EVENT | |
HANDSET_UPDATE_EVENT | events.handset_update.subscribe |
LOCATION_UPDATE_EVENT | events.location.subscribe |
ROAMING_EVENT | events.roaming.subscribe |
SMS_EVENT | events.sms.subscribe |
SMS_DELIVERY_EVENT | events.sms_delivery_report.subscribe |
VOICE_EVENT | events.voice.subscribe |
VOICEMAIL_EVENT | events.voicemail.subscribe |
Consent Revoke
This event will fire when the OAuth2.0 consent is revoked for a subscription.
It allows the application to cleanup user state. This may either be via our revoke flow or from customer support.
Handset Update
This event will fire when a SIM card is used in a new device.
It will contain the previous and current IMEI.
Location Update
This event will fire when the handset is registering at a new location.
Roaming
This event will fire on the first location update in a new country.
It will contain the country code and name for the previous and current country.
SMS
This event will fire every time an SMS is sent or received by the handset.
This contains the from and to address in addition to the actual content of the SMS.
SMS Delivery Report
This event will fire when a SMS delivery report is generated.
This contains the from and to address, and the status for the SMS sent.
Voice
This will fire for when a call is initiated, ringing, answered, sent to voicemail or hung up. It will contain from and to number, call ID and which type of call event it is.
Voicemail
This will fire when a voicemail is left for a subscription.
It contains from and to number and the ID of the voicemail. The actual content of the voicemail may be retrieved by a separate API using this ID.
Code Dependencies
<dependencies>
<dependency>
<groupId>com.wgtwo.api.v0.grpc</groupId>
<artifactId>events</artifactId>
<version>0.1.6</version>
</dependency>
<dependency>
<groupId>com.github.working-group-two.wgtwoapis</groupId>
<artifactId>utils-grpc</artifactId>
<version>cca7093</version>
</dependency>
</depenencies>
Code, Listen for Events
If targeting production, you would need to add authentication to the sample code.
#!/usr/bin/env bash
grpcurl \
-d '
{
"type": ["VOICE_EVENT"]
}
' \
sandbox.api.shamrock.wgtwo.com:443 \
wgtwo.events.v0.EventsService.Subscribe
package com.example.events
import com.wgtwo.api.v0.events.EventsProto
import com.wgtwo.api.v0.events.EventsServiceGrpc
import io.grpc.ManagedChannelBuilder
import io.grpc.stub.StreamObserver
fun main() {
val channel = ManagedChannelBuilder.forAddress("sandbox.api.shamrock.wgtwo.com", 443).build()
val stub = EventsServiceGrpc.newStub(channel)
val request = EventsProto.SubscribeEventsRequest.newBuilder()
.addType(EventsProto.EventType.VOICE_EVENT)
.addType(EventsProto.EventType.VOICEMAIL_EVENT)
.build()
stub.subscribe(
request,
object : StreamObserver<EventsProto.SubscribeEventsResponse> {
override fun onNext(response: EventsProto.SubscribeEventsResponse) {
println("Received event:
${response.event}")
}
override fun onError(throwable: Throwable) {
println("Got error: ${throwable.message}")
// TODO: Reconnect
}
override fun onCompleted() {
println("Connection closed by the server")
}
},
)
println("subscribed to events, waiting.")
// Wait for stream to close
try {
Thread.currentThread().join()
} catch (e: InterruptedException) {
}
}
Example Results, Listen for Events
{
"event": {
"timestamp": "2024-08-02T10:08:55.668065022Z",
"voiceEvent": {
"callId": "e70b8117-6e3d-49e1-83f6-0e7f932e5bb2",
"type": "CALL_INITIATED",
"fromNumber": {
"e164": "+4799948352"
},
"toNumber": {
"e164": "+46724450024"
},
"callerIdHidden": true
},
"owner": {
"phoneNumber": {
"e164": "+46724450024"
},
"sub": "66cd5d7e9d9bc07ae7f042ceb65ad0ba72047bf25ade95b8924d52fb705fd7ac630fa762d4419050d0f982aed86a33b7d4171a3fd4965c53d59dcf040a808c1a"
}
}
}
subscribed to events, waiting.
Received event:
timestamp {
seconds: 1722599642
nanos: 160869380
}
voicemail_event {
voicemail_id: "764ba4ba-9d09-11eb-892b-37b0c646aeaa"
type: NEW_VOICEMAIL
from_number {
e164: "+46161433210"
}
to_number {
e164: "+4751972385"
}
}
owner {
phone_number {
e164: "+46724450024"
}
sub: "66cd5d7e9d9bc07ae7f042ceb65ad0ba72047bf25ade95b8924d52fb705fd7ac630fa762d4419050d0f982aed86a33b7d4171a3fd4965c53d59dcf040a808c1a"
}
Manual Acknowledge
In the below example we enable manual acknowledgement, and set a custom ack timeout. This provides more control and flexibility when handling events.
Code, Manual Acknowledge
package com.example.events
import com.google.protobuf.util.Durations
import com.wgtwo.api.v0.events.EventsProto
import com.wgtwo.api.v0.events.EventsServiceGrpc
import io.grpc.ManagedChannelBuilder
import io.grpc.stub.StreamObserver
fun main() {
val channel = ManagedChannelBuilder.forAddress("sandbox.api.shamrock.wgtwo.com", 443).build()
val stub: EventsServiceGrpc.EventsServiceStub = EventsServiceGrpc.newStub(channel)
val request = EventsProto.SubscribeEventsRequest.newBuilder()
.addType(EventsProto.EventType.VOICE_EVENT)
.addType(EventsProto.EventType.VOICEMAIL_EVENT)
.setManualAck(
EventsProto.ManualAckConfig.newBuilder()
.setEnable(true)
.setTimeout(Durations.fromSeconds(15))
.build(),
)
.build()
stub.subscribe(
request,
object : StreamObserver<EventsProto.SubscribeEventsResponse> {
override fun onNext(response: EventsProto.SubscribeEventsResponse) {
println("Received event:
${response.event}")
acknowledge(response.event, stub)
}
override fun onError(throwable: Throwable) {
println("Got error: ${throwable.message}")
// TODO: Reconnect
}
override fun onCompleted() {
println("Connection closed by the server")
}
},
)
println("subscribed to events, waiting.")
// Wait for stream to close
try {
Thread.currentThread().join()
} catch (e: InterruptedException) {
}
}
fun acknowledge(event: EventsProto.Event, stub: EventsServiceGrpc.EventsServiceStub) {
val request = EventsProto.AckRequest.newBuilder()
.setSequence(event.metadata.sequence)
.setInbox(event.metadata.ackInbox)
.build()
stub.ack(
request,
object : StreamObserver<EventsProto.AckResponse> {
override fun onNext(response: EventsProto.AckResponse) {
println("Event successfully acknowledged")
}
override fun onError(throwable: Throwable) {
println("Error acknowledging event: ${throwable.message}")
}
override fun onCompleted() {}
},
)
}
Example Results, Manual Acknowledge
subscribed to events, waiting.
Received event:
timestamp {
seconds: 1722599642
nanos: 160869380
}
voicemail_event {
voicemail_id: "764ba4ba-9d09-11eb-892b-37b0c646aeaa"
type: NEW_VOICEMAIL
from_number {
e164: "+46161433210"
}
to_number {
e164: "+4751972385"
}
}
owner {
phone_number {
e164: "+46724450024"
}
sub: "66cd5d7e9d9bc07ae7f042ceb65ad0ba72047bf25ade95b8924d52fb705fd7ac630fa762d4419050d0f982aed86a33b7d4171a3fd4965c53d59dcf040a808c1a"
}
Read More
- Events API reference
- See full example implementation for Java: Maven starter - Listen for events.