Eventmaker Leads API

Extracting a UID from the QR-Code

Before creating a lead you must first get the unique identifier of a guest (UID). This UID is available in a guest's QR-Code. Eventmaker QR-Codes contains MeCard that embeds data on the guest such as:

  • the name (N)

  • the email (EMAIL)

  • the company name (ORG)

  • the position (TITLE)

  • the phone number (TEL)

  • the guest unique identifier (UID)

⚠️Note that only the UID is mandatory in the MeCard. It's up to the event organizer for the other fields.

Create one or more leads

With the UID you can then create the lead on the Eventmaker platform. This is done with the batch_create API that allows you to create one or more leads for an exhibitor. Remember that the exhibitor is authenticated by its access_token : Example

curl -X POST -H 'Content-Type: application/json' https://app.eventmaker.io/api/v1/devices/<access_token>/connections/batch_create.json -d @payload.json 

💡replace <access_token> with the exhibitor access token With payload.json :

{
    "connections": [
      {
        "guest_uid": "<guest_uid>",
        "author": "Robin"
      },
      {...}
    ]
  }

💡replace <guest_uid> with the UID extracted in the MeCard In the payload you must at least specify the guest_uid and the author. Sample response :

[
    {
	"_id": "5c6c0c0af897748ba97644f2",
	"guest_uid": "guest uid",
	"exhibitor_id": "5c66dfdcf89774219591baa6",
	"updated_at": "2019-02-19T14:00:42.711Z",
	"created_at": "2019-02-19T14:00:42.672Z",
	"author": "Robin",
	"comments": [],
	"exhibitor_products": []
    },
    {...}
]

You can ignore the comments and exhibitor_products fields.

Get leads details

Creating a lead doesn't give you much information. You can get more data by requesting the lead_guests API which returns a list of fields. These fields are related to the event and are whitelisted by the event organizer, meaning that they decide which fields get returned by this API. Example

curl -X GET -H 'Content-Type: application/json' "https://app.eventmaker.io/api/v1/lead_guests/<guest_uid>.json?access_token=<access_token>" 

💡replace <access_token> with the exhibitor access token 💡replace <guest_uid> with the UID extracted in the MeCard Sample response

{
    "email": "maria.hamilton@gmail.com",
    "first_name": "Maria",
    "last_name": "Hamilton", 
    "company_name": "Apple",
    "uid": "S61LMJY"
}

Working with ciphered QR-Codes 🔐

Some events require ciphered QR-Codes. For these events, your app will need to get back a ciphering key and IV to decipher QR-Code before following the flow described previously. When QR-Code ciphering is enabled on an event you need to get back the ciphering key and IV using this API :

curl -X PUT -d '{ "signature": <signature>}' -H 'Content-Type: application/json' "https://app.eventmaker.io/api/v1/events/<event_id>/exhibitors/<access_token>/activate_license.json" 

💡replace <signature> with the signature (see below how to generate the signature) 💡replace <event_id> with the event_id 💡replace <access_token> with the exhibitor access_token Sample response (when QR-Code ciphering is not enabled) :

{
  "qr_code_ciphering_enabled":false,
  "qr_code_ciphering_key":null,
  "qr_code_ciphering_iv":null,
  "app":"Leads Android"
}

Sample response (when QR-Code ciphering is enabled) :

{
  "qr_code_ciphering_enabled":true,
  "qr_code_ciphering_key":"kHxOFKTAq7xutc8MnAlmrUrQNAW/xXM8V1X5VgB444Q=",
  "qr_code_ciphering_iv":"JWEVPt7lhlNcnfNNyVtnOQ==",
  "app":"Leads Android"
}

If signature is incorrect you will get a 401 status code, 200 otherwise. Computing the signature 🔏 First your app need to be registered into Eventmaker (contact us) and we will deliver you a secret. Then the signing_key must be the concatenation of the secret and the event_id :

<secret><event_id>

Finally you need to sign the exhibitor access token with the signing key using hmac-sha256 :

signing_key = <secret><event_id>
signature = HmacSha256(access_token, signing_key)

Sample code iOS (objective-c) :

#import <CommonCrypto/CommonHMAC.h>
[...]

NSString *key = [NSString stringWithFormat:@"%@%@", kSigningSecret, eventId];

const char *cKey  = [key cStringUsingEncoding:NSASCIIStringEncoding];
const char *cData = [toSign cStringUsingEncoding:NSASCIIStringEncoding];
unsigned char cHMAC[CC_SHA256_DIGEST_LENGTH];
CCHmac(kCCHmacAlgSHA256, cKey, strlen(cKey), cData, strlen(cData), cHMAC);
NSData *HMACData = [NSData dataWithBytes:cHMAC length:sizeof(cHMAC)];

const unsigned char *buffer = (const unsigned char *)[HMACData bytes];
NSMutableString *signature = [NSMutableString stringWithCapacity:HMACData.length * 2];
for (int i = 0; i < HMACData.length; ++i){
  [signature appendFormat:@"%02x", buffer[i]];
}

Sample code Android (java) :

String signingKey = signingSecret + eventIdK;
String toSign = "...";

Mac hmacSHA256 = Mac.getInstance("HmacSHA256");
hmacSHA256.init(new SecretKeySpec(signingKey.getBytes(), "HmacSHA256"));
byte[] result = hmacSHA256.doFinal(toSign.getBytes());
StringBuilder sb = new StringBuilder(result.length * 2);
for(byte b: result)
  sb.append(String.format("%02x", b));
String signature = sb.toString();

Deciphering QR-Code When Eventmaker QR-Code are ciphered, their content will look like something:

E:somecipheredunreadablestuff

When you scan a QR-Code you should always look for the prefix E: and if found, you will need to decipher the content. The content is ciphered with AES 256 using the block cipher mode CBC. Keys, IV and real mecard content (everything after E:) is base 64 encoded and will need to be decoded first (before deciphering process). ⚠️ensure your app works with both ciphered and not ciphered QR-Code Sample code iOS (objective-c) :

NSData *data = [[NSData alloc] initWithBase64EncodedString:content options:NSDataBase64DecodingIgnoreUnknownCharacters];
NSData *keyData = [[NSData alloc] initWithBase64EncodedString:key options:0];
NSData *ivData = [[NSData alloc] initWithBase64EncodedString:iv options:0];
    
CCCryptorRef cryptor = NULL;
CCCryptorStatus status = CCCryptorCreateWithMode(kCCDecrypt, kCCModeCBC, kCCAlgorithmAES, kCCOptionPKCS7Padding, ivData.bytes, keyData.bytes, kCCKeySizeAES256, NULL, 0, 0, 0, &cryptor);
          
size_t bufsize = CCCryptorGetOutputLength(cryptor, (size_t)[data length], true);
void * buf = malloc(bufsize);
size_t bufused = 0;
size_t bytesTotal = 0;
    
status = CCCryptorUpdate(cryptor, [data bytes], (size_t)[data length], buf, bufsize, &bufused);
bytesTotal += bufused;
      
status = CCCryptorFinal(cryptor, buf + bufused, bufsize - bufused, &bufused);      
bytesTotal += bufused;
    
NSData *decryptedData = [NSData dataWithBytesNoCopy:buf length:bytesTotal];
free(buf);
NSString *decipheredContent = [NSString stringWithUTF8String:[decryptedData bytes]];

Sample code Android (java) :

String contentWithoutPrefix = content.substring("E:".length());
byte[] key = Base64.decode(qrCodeCipheringKey, Base64.DEFAULT);
byte[] iv = Base64.decode(qrCodeCipheringIv, Base64.DEFAULT);
byte[] contentData = Base64.decode(contentWithoutPrefix, Base64.DEFAULT);

SecretKeySpec keySpec = new SecretKeySpec(key, "AES");
IvParameterSpec ivSpec = new IvParameterSpec(iv)
Cipher cipher = Cipher.getInstance("AES/CBC/PKCS5PADDING");
cipher.init(Cipher.DECRYPT_MODE, keySpec, ivSpec);
String decodedContent = new String(cipher.doFinal(contentData));

Last updated