Important: This guide describes the “monolithic” Estimote SDK, from  Estimote/iOS-SDK

The proximity detection features in that SDK are now obsoleted in favor of the new Estimote Proximity SDK, available at  Estimote/iOS-Proximity-SDK

To learn more about the new API, see the Add Proximity to iOS app guide instead.

Secure iBeacon advertising with Estimote Secure UUID

Estimote Secure UUID is a security mechanism within Estimote SDK that protects the real ID of your beacons, giving you a better control over the access to their signal. It is optional, can be enabled at any time, and is recommended for every beacon deployment as an additional security layer.

For a high-level overview, see: Are Estimote Beacons secure? How does Secure UUID work?

What’s ahead

Why you should use it

By default Bluetooth beacons regularly broadcast their plain Beacon ID (Proximity UUID, Major and Minor for iBeacon), for all BLE devices in range to detect. This way anyone can sniff on your network, find out the IDs of your beacons, and use them for their evil purposes like:

  • Beacon Spoofing (Cloning) - detecting and cloning your beacon IDs to mimic your beacons at other locations.
  • Beacon Hijacking (Piggybacking) - deploying an app that uses your beacon network to promote their own products.

With Secure UUID enabled, beacons hide their Real Beacon ID by broadcasting encrypted values that change periodically. We call these values Visible Beacon IDs.

How it works

Each of the Estimote Beacons has a unique Beacon Key assigned to it in the manufacturing process which is only known to the beacon and Estimote Cloud.

Secure UUID algorithms use the Beacon Key, together with a timestamp of the most recent rotation, to encrypt and decrypt Visible Beacon IDs. A beacon itself is responsible for the encryption—it generates new Visible Beacon IDs based on a specific “rotation” interval, and broadcasts them in an iBeacon packet. Decryption happens in Estimote Cloud where the Beacon Key is resolved, thus uniquely identifying the beacon. Between the two—the beacon and the Cloud—there is an iOS/Android device that listens to the Visible Beacon IDs, and communicates with the Cloud to find out the Real Beacon ID.

Since the device acts merely as a “proxy” or a “middleman”, it never knows the Beacon Key. Otherwise, a malicious party could extract the key from your app, and be able to decipher all future Visible Beacon IDs. Putting the decryption in Estimote Cloud prevents that, but of course, it makes Secure UUID require active Internet connection to work.

Info: Our SDK uses caching to optimize the network usage, which means that requests to Cloud happen only when Visible Beacon ID rotation occurs. Given the default rotation interval, it means 1 request-response with a total size of 1.5 kB, sent every ~ 17 minutes for each of your Secure-UUID–enabled beacons. With an average Internet connection, it should take around 200 ms to complete.

Secure UUID mechanism step by step:

  1. Beacon generates a new Visible Beacon ID.
  2. Beacon broadcasts the Visible Beacon ID.
  3. iOS/Android device detects the Visible Beacon ID.
  4. iOS/Android device communicates the Visible Beacon ID to Estimote Cloud.
  5. Estimote Cloud uses App ID and Token to authenticate the request.
  6. Estimote Cloud verifies that the beacon belongs to the account.
  7. Estimote Cloud resolves the beacon’s Real Beacon ID.
  8. Estimote Cloud communicates the Real Beacon ID to the device.
  9. iOS/Android device recognizes the Beacon.

Setting it up

Enabling the Secure UUID feature is a 3-step process:

  1. Set the App ID and App Token in your app.
  2. Enable Secure UUID on your beacon.
  3. Modify your code to use secure detection.

Step 1: Set the App ID and App Token in your app

First, you need to get your App ID and App Token:

  1. Log in to Estimote Cloud.
  2. Navigate to the Apps section.
  3. If you don’t have any apps yet, create a new “Your Own App”.
  4. The App ID and App Token are displayed next to your app’s name.

The next thing to do is to include the App ID and App Token setup in your code:


Add the following line in the AppDelegate’s application:didFinishLaunchingWithOptions: method:

ESTConfig.setupAppID("YOUR APP ID", andAppToken: "YOUR APP TOKEN")
[ESTConfig setupAppID:@"YOUR APP ID" andAppToken:@"YOUR APP TOKEN"];


Add the following line in the onCreate method of your Application subclass:

EstimoteSDK.initialize(getApplicationContext(), "YOUR APP ID", "YOUR APP TOKEN");

Step 2: Enable Secure UUID on your beacon

You can do it in 3 different ways:

  • Using the Estimote app, by connecting to each of the beacons and turning the Secure UUID on in the iBeacon settings.

  • Using Estimote Cloud, by enabling Secure UUID for selected beacons, and then connecting to each of them to apply the changes.

  • Programmatically, by changing the ESTSettingIBeaconSecureUUIDEnable setting of your beacons:


    let enable = true
        completion: { (enabledSetting, error) in
        // handle success/failure
    BOOL enable = YES;
    [device.settings.iBeacon.secureUUIDEnable writeValue:enable completion:
        ^(ESTSettingIBeaconSecureUUIDEnable * _Nullable enabledSetting,
          NSError * _Nullable error) {
        // handle success/failure


    DeviceConnection connection = connectionProvider.getConnection(device);
    boolean enable = true;, new SettingCallback<Boolean>() {
        public void onSuccess(Boolean value) { /* ... */ }
        public void onFailure(DeviceConnectionException exception) { /* ... */ }

    (to learn how to access the configuration APIs, check out Connecting to beacons)

Step 3: Modify your code to use secure detection

The last step necessary to get it all up and running is to switch to the secure equivalents of the beacon detection classes:


  • ESTSecureBeaconManager in place of ESTBeaconManager or CLLocationManager,
  • ESTSecureBeaconManagerDelegate in place of ESTBeaconManagerDelegate or CLLocationManagerDelegate.

A basic Secure Beacon Manager setup could look like this:

class ViewController: UIViewController, ESTSecureBeaconManagerDelegate {

  let secureBeaconManager = ESTSecureBeaconManager()

  override func viewDidLoad() {
      self.secureBeaconManager.delegate = self
      let beaconRegion = CLBeaconRegion(
          proximityUUID: UUID(uuidString: "B9407F30-F5F8-466E-AFF9-25556B57FE6D")!,
          major: 1234, minor: 5678, identifier: "my secure beacon")
      self.secureBeaconManager.startMonitoring(for: beaconRegion)

  func beaconManager(_ manager: Any, didEnter region: CLBeaconRegion) {
      print("Secure beacon detected!")

  // ...
@interface ViewController () <ESTSecureBeaconManagerDelegate>
@property (nonatomic, strong) ESTSecureBeaconManager *secureBeaconManager;

@implementation ViewController

- (void)viewDidLoad {
    [super viewDidLoad];
    self.secureBeaconManager = [ESTSecureBeaconManager new];
    self.secureBeaconManager.delegate = self;
    [self.secureBeaconManager requestAlwaysAuthorization];
    CLBeaconRegion *beaconRegion = [[CLBeaconRegion alloc]
        initWithProximityUUID:[[NSUUID alloc] initWithUUIDString:
        major:1234 minor:5678 identifier:@"my secure beacon"];
    [self.secureBeaconManager startMonitoringForRegion:beaconRegion];

- (void)beaconManager:(id)manager didEnterRegion:(CLBeaconRegion *)region {
    NSLog(@"Secure beacon detected!");


Keep in mind: ESTSecureBeaconManager won’t detect any non-secure beacons. If you want to mix-and-match, you can safely use both the Secure and the regular beacon managers simultaneously in your app.


Initialize your BeaconManager as before, and then use SecureRegion in place of Region:

// range for Secure-UUID–enabled beacons using a secure region
beaconManager.startRanging(new SecureRegion("secure beacon", myUUID, 1234, 5678));

// you can range for non-secure beacons as usual, using that same manager:
beaconManager.startRanging(new Region("plain-old beacon", myUUID, 9876, 5432));

Adjusting ID rotation interval

You can modify how often the Visible Beacon ID rotates:

The interval is equal to 2scaler seconds, and the default scaler value is 10—which gives a rotation period of around 17 minutes.