I'm Noah [phonetic].
I'm here with my colleague Nick [phonetic].
And we're here to talk to you about what's new in Passbook in iOS 7.
Now, some of you have been building really awesome things on top of Passbook already, and we've had a bunch of requests from you for enhancements, for new features, and we've addressed a ton of those, and we've added some new stuff as well.
And I'll be going into all of that in a lot of detail.
Some of you have looked at Passbook before and considered using it but found it didn't quite fit your use case at the time.
And we've made a couple of changes that may affect that, so I'll be calling those out as well later.
And, finally, some of you are entirely new to Passbook and just kind of curious about what's going on.
So I'll be while our talks last year went into a bunch more detail about how to get started, how to build your first pass, and that kind of thing, I'll still be covering some high level concepts just so you have some idea what's going on.
So without further ado: let's get started.
There's three main topics I'll be covering today.
First the Passbook ecosystem: the different parts, how they fit together, how they all talk to each other.
Second: what's new, what we've added to passes, to our APIs, the app.
And finally a couple of tips, tricks, ideas that might help you with your debugging and your development of Passbook integration.
So let's go to the first of these, the ecosystem.
To start with: what is a pass?
Well, it's just information like any other, but what makes a pass more useful than just a photo of a ticket, for instance, is first, that it can be relevant to a time and place.
And second, that it can be used for something in the real world: to get into something, to buy something, to do something.
So how does a pass get from you to your users?
Well, it starts with your server, which generates the pass.
Then it goes through your website, or an email, or an app of your own if you have some existing flow like buying a boarding pass.
From any of those three, it goes into Passbook, into the user's pass library, and from there they can interact with it.
There's a couple other places that it can show up on the system, and I'll talk about those more in a bit.
But the core of it is that it comes from these apps, goes into your library, and that's kind of that.
Now, a thing about passes: since they represent real-world information, you expect them to be up- to-date.
They should always reflect the current state of whatever they're supposed to be used for.
And we could make you go through that whole flow all over again, direct your users back to your app, send them an email, back through your app, but that would be a huge pain and no one would do that.
So we have a better system, and it's built on top of the Apple Push Notification Service.
Your server sends us a push, we make a request to your web service, and you send us down a new version of the pass file.
And that seamlessly replaces the existing pass in the user's pass library, and to them the pass is magically now up-to-date.
So the user has your pass, it's up-to-date, how do they then use it?
Well, they bring their device to your location.
You scan it, the barcode on it, with some kind of point of sale system.
That then talks to your server, which checks whether the pass is valid, whether it can be used for whatever transaction they're trying to complete, and finds out, okay, the pass is available to use.
It sends that information back down, you complete the transaction and that's that.
Now, if something changes about the pass as a result of this transaction, like if you've used a coupon that can no longer be used, or if you have a store card whose balance you're updating, your server might take that opportunity to then send an update notification to the pass and get it up-to-date.
So that's just a vague high level overview.
Passes are information that can be used for something in the real world.
They come from your server.
They get into the user's pass library via your apps or via Mail or Safari.
And they are then used by scanning the barcode on the pass and checking its validity with your server.
And finally they can be updated via the push system to make sure the pass has the most up-to-date information.
So that's the ecosystem.
Let's talk about what's new in Passbook in iOS 7.
First, we've added ways for you to enrich the content of your passes, to make them more useful, work better, look better.
We've added easier ways to get passes into Passbook, both via APIs and via some really cool new user-facing features.
We've given you more control over the relevance of your passes, over when they show up on the lock screen of your user's device.
And, finally, we've added better support around the whole using-passes thing.
I'll be more clear about that later on.
So let's talk about the first of these, the pass content.
A pass is kind of structured like an app bundle: it's a folder that's zipped up, and the contents look like this.
You have your pass.json which defines what the pass is, how it behaves, how it looks.
You have a couple of localized string files, the lproge [phonetic] folders that you see here which contain strings that get substituted into your pass.json for user-facing strings.
You have a couple of icons and images that we use to display the pass in Passbook and elsewhere in the OS.
All of that is signed and zipped, and there's your pass.
So you may have noticed that things look at little different in iOS 7, and Passbook's no exception to that.
Things have less gradients, they have less shine, subtler shadows, that kind of thing.
And for the most part that won't affect you.
We already will apply the new look to your passes.
But if you've been making a particular effort to match the iOS6 style, if you've been creating your own gloss or if you've been sizing images to fit precisely within the boundary of the strip or anything, then that's going to look wrong now.
Your passes will look slightly out of place.
It won't be the end of the world, but it will look slightly off.
So the rule of thumb for that is, well, don't do that.
Follow our guidelines, supply us the images in the style and format that we expect, and trust that we'll do the right thing when and if the appearance changes of what we're applying to passes.
So there is one change to the appearance that's going to affect your images that you will probably need to adapt for, and that's that passes are now the full width of the screen.
They're 320 points, up from 312, which means that your strip images need to change as well for that.
We'll currently take your strip image and scale it up a little bit.
But if you want it to be pixel perfect, which of course you do, then you want to change those images for iOS 7.
And we also no longer expect you to etch your logos.
You don't need to apply shadow.
Just give those a solid color, and it will fit right in, it will look great.
Finally, while iOS 7 Passbook will only run on Retina devices because those are the only ones that support iOS 7 we aren't in iPad, for instance you do still need to expect that your passes are going to show up on iOS 6 devices.
So you might have them on the non-Retina screen on the iPhone 3GS for instance.
So still provide non-Retina images.
Even though a lot of your users are going to be on iOS 7 this fall, be ready for your passes to end up pretty much anywhere.
So let's talk about grouping, which is a behavior we haven't gone into a lot of detail before, but you've certainly noticed it if you've been producing multiple passes.
Passes group automatically.
Based on a couple of rules, details not very important, but sometimes the grouping behavior is not exactly what you expect.
If you have an itinerary, for instance, for a couple different people, we might be grouping all those passes together into one morass which you might want to have better control over.
So we now have this grouping identifier key.
It's just a string.
You specify it and any passes of yours that have the same grouping identifier will group together.
Any that have different ones will group separately.
So you can use this on event tickets and boarding passes, which are the passes that are most likely to be grouping in these kind of cases, and that's useful if you're doing something that involves an itinerary or a multi-day event.
So, if you need that, use it.
That's what it's there for.
[ Applause ]
So let's talk about something different entirely: date fields.
This is a feature that we added in iOS 6, basically to make users' experience around localization better.
What we do is you give us an absolute timestamp and a date style short, medium, long, et cetera and we format the time in a format that the user will expect to see.
So if they have their locale set to show three o'clock or 15.00 or anything like that, we'll show your time in the format they expect it to be, and it will look right, it will fit in.
So something that comes out of our using this timestamp format is that we get automatic time zone adjustment.
So if you have something like a pass that specifies that it occurs in in 12 p.m. Pacific time, then the user will see that as I always get this stuff wrong 3 p.m. Eastern.
So that's great.
It usually works in the way that the users expect it to, but sometimes you don't want that behavior.
Sometimes you want to show a time in the local time zone that it's going to happen.
If you have a boarding pass, for instance, you want to show the departure time as when they get to the gate.
Or, if you have a hotel check-in, for instance, then again you want to show that as the time that it is there.
Because people have trouble converting between time zones, like I just did, and you want to help them out with that.
So what we now allow you to do is to control how that works.
And the workaround that some people have been using for this is to just use text fields and say "3 PM" for instance.
And that works, your users will probably get it, but it's not the best experience.
It could be better, and we like making things better.
So we now allow you to disable that time zone adjustment.
It's just a key on date fields.
You say "ignore time zone" and we drop that.
We show it always in the local time zone that you specify.
The format hasn't changed: you can't just leave it out because we're still validating against it.
But what you should probably do here is specify the local time zone that whatever time you're trying to show is happening in.
So iOS 6 device users will get the right experience, more or less, and iOS 7 ones will get this nice new ignoring-time-zone behavior.
So that's date fields.
Let's talk about the back of your passes, about app links.
This is a feature that we added for a couple of reasons.
It can help promote your apps, and it provides easy access to the apps if they have some way of interacting with a pass in the user's pass library.
So it looks like this.
You have this banner at the top of the back of your pass, kind of like the one in Safari.
It shows your app icon.
It shows a button that will either take them to an App Store page which will let them install it if they don't have it already.
And if they do have it then it will let them open the app right from the back of your pass.
So if you have a store card, for instance, this can let them easily get into the app and check their rewards or anything like that.
So the question that arises with these app links, particularly when you have an app that can provide multiple passes like an event app, for instance, is, well, which pass did the user just come from?
You know that they got into your app, but you have no idea what pass they want to interact with.
You might have them go through your list of passes you have in your library and say, you know, which pass are you talking about?
But that's not ideal.
It's an additional step, and they already chose this pass when they flipped it over to get to your app.
So what we now allow you to do is provide a context URL which we launch your app with as soon as the user taps the open button on the app link.
And so that's really useful to immediately get you the information as to what pass they just came from.
You might even embed additional information in the URL itself.
But thanks to this next feature you don't actually even have to do that.
Because what we now have is pass metadata.
You can embed a dictionary of arbitrary information in your pass, and your app can read it off with a user info property on a PKPass object.
So what this means is that you can get semantic information about the pass without having to make a round trip to your web server.
You don't have to check the serial number with your server and pull down additional information, wait for the network latency and all that.
It's just right there.
So your app can quickly and easily show information about the pass to the user.
It can even do it in conditions where there's no network access on an iPod, for instance.
So that should be really useful if you've got an app that integrates with your passes.
And one thing about this is that while you can probably trust that this information did come from you, because you signed the pass, it might not necessarily be up-to-date.
So if you have anything valuable or sensitive, like a store card balance, for instance, you should still check it with your server if you have the opportunity.
So that's app links.
Let's talk about text links, and the text on the back of your passes.
The idea for these is that you can provide additional information related to your passes.
So you can provide contact information or the location of an event.
And to make that more useful for your users, we run data detectors on them: we turn things that look like useful information into links.
So an address opens maps, a phone number allows them to call it, that kind of thing.
But sometimes that doesn't behave right.
You can see here I have a confirmation number that's being confused as a phone number, and an address that I don't know whether this exists but it's not a real place which we shouldn't be giving directions to.
So what we now allow you to do is control this and set what kind of data we detect.
So your confirmation number stays clean of links.
Your things that you don't want to be directions to they don't turn into directions links.
And that's going to be really helpful.
And your users probably weren't bothered by this, but it was a little confusing.
And this makes your passes look better.
So the way this works is an array of strings containing the list of data detector types that you want us to run.
So that can be phone numbers, addresses, emails, anything like that.
You just provide the list of what you want us to detect, and anything you leave out we won't look for.
So the default, of course, is "all".
If you don't provide this key, then we just do our existing behavior.
But if you're seeing any issues with data detectors turning up when you don't want them to, use this.
It will help.
I mentioned URLs, and this is something that we've heard a lot about from you guys.
Specifically, that when you embed URLs on your passes, they look bad.
They're long, they're ugly, they're opaque.
You can have a long URL with your company's website, or you can have a URL-shortened one which is not your company's website but is even more opaque.
So that's not the ideal user experience, and you have to include lots of explanatory text saying "if you want to talk to our nice support people, tap this link below," et cetera.
So what we've added to fix this is embedded URLs.
[ Applause ]
So it works like this.
There's a new key on your field that's called attributed value which is in addition to the existing value key.
So you can see here I've included this with more information, explanatory text, and I've also included a much shorter at least to the user's eye version of this which does the same thing and looks way better.
So it's a standard HTML-style link tag.
You've probably seen it before, but it's not full HTML.
If you want to make your text bounce around the screen or do marquees or sparkle, no, no, we don't let you do that.
And it's only on back fields, of course, because as before we only allow links there.
But that should be a great way to make your passes look way better and to simplify things.
And basically it means your users have a way better experience with your passes.
One note about this.
iOS 6 devices have no idea what an attributed value key is.
You still need to include the value for backwards compatibility, so: do that.
Let's review all this.
First, we have the new look.
If you've been matching the old style by making your own gloss or shadows or fitting things to the dimensions that you thought were going to be forever...
don't do that.
Just follow our guidelines, and we'll do the right thing with your graphics.
We now allow you to do date fields without time zone adjustment.
We've added app links for context URLs along with metadata which allows you to pull information off your pass without having to make a round trip to your server, consume resources, et cetera.
And, finally, we've given you better links on the back of your passes via more control over data detectors and via the new embedded URLs.
So that's what's new in pass content.
Let's talk about how you get passes into Passbook.
We've made a lot of changes here.
The first one well, first, an overview.
Passes, as I said, come from your server.
They go through Mail or Safari, which can handle things on their own, or in your apps you have a couple of APIs, the PKAddPassesViewController which allows you to present a pass to be added to a user's pass library, and a couple of PKPassLibrary methods that allow you to update and remove passes from the library.
And the thing about this is: if you have a bunch of passes to get to the user you have to add them one at a time, one after another, present an add-pass view controller, present another one, et cetera, and your users are either going to get fed up going through those or they're not going to get fed up but they're going to send you nasty emails.
And we want to save you from that.
So what we've added is a new way to get multiple passes into Passbook.
And to demo that I'd like to bring up Nick Circosta [phonetic].
[ Applause ]
So as Noah said we've got some great new features to PassKit in iOS 7 to allow you to get passes easier than ever.
So what we have here is a relatively simple application, a collection-view-based application and let's just go ahead and run it and see how it looks.
[ Pause ]
Yay, we're all going to a film festival.
So if we were, say, running this application on iOS 6, and a user wanted to add a movie ticket for each one of these films, they would most likely tap each on in turn, and then you'd present an add-passes view controller for each one and ingest it into Passbook.
But we're going to do something a little bit cooler now in iOS 7.
So what we have here is a method that's called when we tap the add button.
And as with anything, when we're working with the pass library, the first thing we want to do is, of course, get a reference to the pass library.
Same as always, we do a PKPassLibrary alloc-init [phonetic].
Now, next we're going to call this new method we've added, called -addPasses:with CompletionHandler:.
Now, in this particular instance, we're passing in this array of selected films which contains all the films the user has selected in the UI.
And it's going to return it to the completion handler one of two PKPassLibrary add statuses.
So let's take a look at the first one.
As with all these notifications, you should always make sure that you're performing any operations on the main thread.
So the first status you might receive is a PKPassLibraryShouldReviewPasses.
Now this means that the user has tapped "review".
Now, you're going to initialize a PK add passes view controller when this occurs, and what you might notice is that instead of just passing in one pass like in iOS 6, we can now pass it an array of passes, which in this case is our selected films array.
You're going to obviously want to set the delegates so you can get the notification callback when the user is going to just dismiss it, and then we're just going to present it to our user.
Now, the second status is the PKPassLibraryDidAddPasses.
Now this means that the user tapped "add all" and chose not to review the passes.
Now, we're also going to update our movie posters UI, and I'll touch on that method in a moment.
I do want to add, just as a piece of information to you, that in a future seed this is not in seed 1 we will be adding a third status to determine if the user cancelled adding those passes.
So as we continue down the code we also have the "add-passes view controller did finish" delegate method.
And in this particular instance we're also going to update our movie posters when that occurs.
Now, I've got a movie posters, relatively simple method here, we're going to use the pass library -containsPass: method to check to see if those passes were actually added to Passbook.
And when that occurs we're just going to set a simple property in our model and then read our collection view and fit a nice fade on the passes we have.
Let's go ahead and run that.
[ Pause ]
Cool. Now I really want to see Epic, Iron Man, and the new Star Trek movie.
Let's tap add.
Now, as we said, the user is going to be presented with this alert, and they can choose to either review or add all.
Add all just means add it to Passbook.
Review will mean "let me see those passes", so we're going to tap "review".
And there we have our three movie passes.
And when we do that we're just going to tap "add all", they look pretty good to me, and nicely animate those out.
[Applause] And with that back to Noah.
[ Pause ]
So that's pretty cool.
Let's talk about a bit of the details behind it.
It's a method on PKPassLibrary as Nick said: -addPasses:with CompletionHandler:.
And you can call this and it will just present that alert where the user can then easily just tap "add all" or, as you saw, "review".
If it's "add all" then your passes just go into their pass library.
There's nothing more that you have to do.
If they tap "review", though, you're responsible for then presenting a PKAddPassesViewController, which has this new initializer, -initWithPasses:.
So that will allow them to then choose to add all the passes or cancel out.
And as you might gather from that, both these APIs are all or nothing.
If the user doesn't want to have one of the passes then they have to cancel the whole thing or go back and delete it later, which would be kind of a pain.
So what you should do, as you just saw in this demo, is provide your own UI for choosing which passes they want.
If you have any situation where the user is going to choose from multiple passes, do that first, then present this, and you'll be good to go.
So that's the new API we have around adding passes.
Let's talk about sharing.
You may have noticed, if you've used Passbook in iOS 7, that each pass now has a share button in the corner.
And when you tap that it brings up this sheet which allows your users to send passes via mail or AirDrop or iMessage.
And this is really good for some use cases, and you may be possibly worried about it for others, but I'll talk about that in a second.
What this means is that if you have a pass that you want to be in a bunch of peoples' hands, that is now super easy.
They just say, you know, "hey, friends, I went to Store, I got Thing, Thing is cool, you should go to Store and get Thing: take this pass".
If you have a situation where you've given one user multiple passes that belong to multiple people, then they can then hand out this movie ticket to their friends they just bought for this everyone-going-to-see-a-movie kind of scenario.
And, as I said, you might now be worried about this because your passes might now be in multiple places and, "oh no, where's my security model?"
That was already very much possible.
Your users could forward emails around, they could share screen shots.
You might even have more legitimate use cases like restoring from an iCloud backup or syncing from one device to another.
So it's just now way more easy, and we've made the user experience around it better, as we sometimes do.
So the key thing to take away from that is that if it matters to you that your pass is on multiple devices, validate them.
Check the barcode: that's what it's for.
So that's sharing.
Let's talk about something that you may recognize from last year, the Add to Passbook badge.
This has proved to be really useful.
Users look for it, they recognize it, they know that it means "I can tap this, I can get a pass, it will be easy, it will be awesome".
And it's great for using in content, in websites and email...
in body content.
But we've seen a couple of cases of people thinking they have to use it and wedging it into their UI somewhere where it doesn't fit sticking it in a navigation bar or in an action sheet.
And you don't have to do that.
Just design for your app.
If you have some custom look that this badge will not fit in, don't use it: use your own thing.
It will be all right.
So this badge ties into a new feature that we're really excited about that some of you may have seen already, called code scanning.
And the idea here is it's a really, really low-friction way to get a pass into your user's hands.
You don't have to send them to a website, you don't have to get their email address, you don't have to get them to install an app: it's just there.
And the idea is you put a URL to a pass into a 2D barcode, and from Passbook they can scan that code and turn it into a pass.
So we've had a bunch of ideas about how you can use this.
I'm sure you'll come up with many more.
But let's talk about these a bit.
You've probably seen codes being used in marketing materials that say, hey, go to our website, scan this code instead of typing it in.
But that's not the only option.
Your codes can be anywhere.
If you're printing something individual like a receipt, or a paper ticket for some reason, then you can put a code that's unique to that user on that receipt saying, hey, here's a coupon for Thing related to Thing-You-Just-Bought.
Or, on an event ticket, you can give someone a Passbook version of their paper pass or paper ticket rather.
But even if you are printing a single code that's going to end up in a lot of places, in a magazine ad or on a banner or anything like that, they don't have to point to a single pass.
You can just point that URL at a web service that can send down a unique pass.
So you might be able to get some information on how many people are using your passes.
Or, you could do something like the first N people who scan this code get this really awesome pass, that kind of thing.
So there's a bunch of possibilities here.
And to show you one of the ones that we've thought about and implemented, I'm going to bring up, again, Nick.
[ Applause ]
We're really excited about pass scanning in iOS 7 so I'm going to give you a quick demo here.
What we have here is a simple web form for a survey running outside our movie theaters on a nice little kiosk.
Nothing really advanced, just some simple drop down fields, and we'll make sure those values are correct.
And we're going to click all done.
Now, that's going to present the user with a nice QR code that they can scan with their Passbook device.
But you may be asking, well, what exactly happens here?
So let's take a look at the URL that we're going to be putting inside here.
So the URL is pointing to a web server that's running on this local laptop.
And you may be wondering, well, why are there a bunch of post variables on the end of this URL.
Well, as Noah said, you don't actually need to point to a static PK pass file.
We can just point to a generation service and that [inaudible].
And you may be asking, well, why don't we just, say, send those variables away.
Well, the interesting thing in this scenario is that this kiosk doesn't actually have to be live connected to the internet in any way.
It can just be all locally running and still be dynamic.
And the nice thing about this is, of course, prior to iOS 7 the user would have to enter some sort of email address for you to send them a pass and now they don't.
One thing we do want to point out is that if you are running a generation service, in this particular case it's in PHP, do remember the PKPass MIME type in your header so that Passbook knows that you're giving us down a pass.
So, without further ado, let's go and scan this one.
So we're going to launch Passbook in iOS 7.
And, as Noah said, some of you may have noticed there's a scan code button.
So let's tap that.
In this particular case we're going to give our users a really nice treat for filling out our form.
Who doesn't love free popcorn?
And that's pass scanning.
[ Applause ]
So we're pretty excited about that.
We can't wait to see what you people do with it.
Let's talk about a couple of details here.
First the URL that you give us has to return a pass.
If you point us to a website and try to get your users fill out an extra form or whatever not going to work.
We will drop that on the floor and say, hey, sorry, this is not a pass.
So the URL has to be HTTPS just like your web services.
We like things to be secure.
And this supports any of the standard Passbook barcode formats, QR, PDF-417, and Aztec.
Let's review all this.
First, we have the new add-multiple-passes API on PKPassLibrary and PKAddPassesViewController.
And something I didn't mention: the add-pass view controller, you can still use that by itself.
If you want to add multiple passes and you always want the user to see them you can do that.
But if you're using the PKPassLibrary API, if the user chooses to review the passes, you have to use the add pass view controller then to show them the passes that you're trying to get into their library.
We have sharing which is great for cases where you want your pass to be in multiple places at once.
But it also means that since it's much easier than it was before, you should be validating your passes if you care about them being on multiple devices.
Just make sure that you're doing that.
And, let's see.
So we have the Add to Passbook badge which we still encourage you to use.
It works great in content.
If you're doing it in an app, use it where it's appropriate.
Don't try to wedge it in places where it doesn't look right.
And, finally, we have the new code-scanning API which is really cool and is a super low friction way to get passes into users' pass libraries.
So that's what's new in getting passes.
Let's talk about relevance which I mentioned earlier.
The idea of your passes showing up in your lock screen is that it's really, really easy to get to them.
It's a single swipe away.
Users don't have to open their phone and unlock it, dig through their apps, find Passbook, dig through their passes, find your pass, et cetera.
It's just right there when they need it, and that's great.
Users love that they have this quick access.
And it's the most important method that you can use to get your users to use your passes.
If your pass is relevant where they're ready to use it, they will recognize that and use your pass, and you'll get that usage.
So there's something that we've seen some confusion about, both from users and developers, which is the difference between relevance and notifications.
If you change something about a pass, that generates a notification: you have something saying, hey, there's something new here.
Relevance is passive, so to speak.
It's a way to make your passes available when they're ready to be used.
So we just wanted to clarify that.
In iOS 6, the API we introduced was based on geographic coordinates, on points on the map.
You could specify ten locations with geocoordinates and whatnot, and within a certain range of those places we'd make the pass relevant based on the pass style and other factors.
And if you wanted to change any of those locations, if you had a bunch of them, more than ten, and your user was in a particular area, or if you had locations that moved around, vehicles trains, for instance then you would have to push an update to the pass to get those new locations into it which is not the ideal way to do that.
So we have a new API for this.
It was meant to address some of the requests we got about this from developers.
It's called proximity.
It's based around iBeacons, which you might have seen mentioned in the keynote on Monday.
The idea is this API on Core Location which allows you to have devices that broadcast a unique identifier over Bluetooth.
And the way that we're using that since Core Location provides, of course, APIs to pick up that broadcast is that we can now make passes relevant whenever they're near one of these devices.
And that allows you a ton of extra flexibility.
It means that you can have any number of locations as long as they have beacons broadcasting the same unique identifier.
If you have a location that moves around, like a taco truck, you can just keep a beacon with you, and you don't have to update the pass to say "here is where I'm going to be" because the pass is already going to be relevant wherever you are.
So that's really cool and we're really excited about it.
Let's talk about the API.
It looks kind of like the locations one, only instead of a pair of coordinates you're just specifying a unique identifier.
And Passbook will look for that identifier, and when it is detected your pass becomes relevant.
It's really simple, it's really easy, and it should help you a lot with more flexible conditions for pass relevance.
Of course we support up to ten different beacons, which is less important than it was with the location API because the beacons can all be broadcasting the same unique ID it doesn't really matter how many there are but if you want to do something different with those, if you want to use, for instance, different relevant text for different beacons in a department store, for instance, then you can have multiple beacons in your pass, we'll look for those and display the appropriate text when we detect the beacon.
And, finally, something really cool about this is that iOS devices running iOS 7 can act as beacons themselves.
So if you have a point-of-sale app or something that is already integrating with Passbook you now have a really easy way to make your passes relevant when they're near that point of sale.
You just have your app broadcast the beacon ID and we'll pick it up, and your pass will be on the user's lock screen and you'll be ready to use it.
One final thing about relevance.
Something that we've had some requests for is a way to control how far away a pass becomes relevant.
Because we use different radiuses for these, and if you have, for instance, a bus station that's using boarding-pass-style passes, then you might see complaints from a user saying, hey, this pass is becoming relevant like a kilometer and a half away, what's going on with that?
And the reason would be, of course, that we size boarding-pass relevance for an airport or so.
So what we now allow you to do is just control that distance.
You can specify a radius around which your pass will become relevant and note that that's a cap, not a replacement for our value.
So if you want to make your pass relevant all over the Bay Area, then you're going to have to put out a lot of beacons or something.
So let's review all this.
First, relevance is a quick, easy way for users to get access to your passes.
Shows up on their lock screen.
They can swipe, get to the pass, move on with their lives.
Relevance and notifications are two different things.
One is active, one is passive.
Beacons now allow you to have way more flexible relevance by setting up these devices and broadcasting a unique identifier.
And, finally, we allow you to control the distance at which your pass has become relevant when using location API.
So that's relevance.
Let's talk about updates.
Now, this hasn't changed much since iOS 6; we're just calling out a couple things about it.
And first off, if you're not using updates when your pass can change, you should be.
It means that your pass can be up-to-date, can stay alive with whatever information it's supposed to represent.
If you've got a boarding-pass-type ticket or a store card that doesn't update when something changes about it, then you're kind of missing out on an opportunity to make your user's experience way better.
So a thing about updates is that if you include a change message for fields that have changed then we show it as a notification to the user.
And if you're going to use that you should follow the same principles that you would use when sending notifications via an app.
You don't want to nag your users.
If you send a push every couple of hours to someone's store card saying, "hey, there are things in our store, hey, check out this other thing in our store", they're eventually going to get fed up with that.
They're going to turn automatic updates off and you'll lose that channel to your users.
So use them sparingly.
Make sure there's something the user cares about when you're updating your pass.
So I mentioned that we've made some changes around using passes.
As I mentioned, the idea is that you scan the barcode on the user's pass, check it with your server, and then complete whatever transaction you're going through.
And so the code scanning feature that we showed off a minute ago is actually based on an API that's now available to you in iOS 7.
And it's on AVFoundation.
It's part of the camera metadata thing.
I'll refer to the talk that talks about it in way more detail later.
And so what this means is that if you have a point-of-sale app or something, like I mentioned earlier, then you can now have that kind of be an end-to-end integration.
It can make the passes relevant, and now it can scan the passes for you, and you can then do whatever you need to do with them.
But this means you can make better point-of-sales and improve your user's experience around their passes.
There are some third party APIs people have been using already for this, but we think this one's kind of great.
And, of course, it supports all the pass barcode types like I mentioned earlier.
[ Applause ]
So let's talk about expiration.
Something we had a lot of requests for again, both from users and developers is a way to know when your users can no longer use a pass.
So what we now allow you to do is to mark a pass as expired in the Passbook UI.
We gray out the barcode, we show "this pass has expired" in whatever language, and that is basically just a way that you can cue your users and say, "hey, don't bother trying to use this pass: it's been used already".
There's two keys that you can use for this.
The first is an expiration date, after which we'll automatically mark the pass as expired.
And the second is a voided key which you can push to the pass if you want to immediately update it if someone has just used their ticket or if their store card is now entirely out of funds or anything like that.
And you should note that this is not an absolute.
You could be looking at a screen shot of the pass, the update might not have made it to the pass, so this should not be your form of security just graying out your barcode.
It's really just meant as a visual cue to your users to let them know when they can and can't use a pass.
So as before, if it matters to you about your pass being used multiple times or being on multiple devices: validate it.
Check the barcode with the server.
That's what it's for.
So to review that, we have the code-scanning API now available on AVFoundation, and we have these new keys to expire your passes, to mark them as expired in the UI.
And, again, if it matters to you your pass being on multiple places or used multiple times: validate them.
Check the pass with your server.
So that's what's new.
Let's talk a couple of tips, tricks, things to help you with your development and make your Passbook integration better.
First, we have some developer settings which you may have seen before.
They're in Settings Developer.
And they're really useful for debugging your passes and your web services and all kinds of things.
First, there's a logging switch, which allows you to see a bunch of extra information about what we're doing, about what your pass might be doing.
If you have validation errors they'll show up there.
If you have weird things happening with your web service like [inaudible].
We have a switch to allow HTTP services.
If you're doing some early development, if you don't have your server's certificate set up, you can turn the switch on, point your passes at some local server without any validation and it will just work.
And finally, we have a new switch which ties into a feature that we haven't really talked about before but that some of you may notice, which is rate limiting.
So if you push a punch of updates to a pass in a row, that means we have to keep downloading the pass over and over again, and that uses the user's battery, it uses a bunch of your server resources.
And so we will throttle that back.
If we get a ton of updates in a row we'll start decreasing the rate at which we actually check for the pass.
And that helps users and means if you have some unexpected issues in your push system then you're not going to get an unexpected spike of server load, which is great.
But if you're testing something, if you're actually trying to send a ton of pushes to a pass in a row, then that's kind of a problem for you.
And so you can turn this on and we will update the pass immediately for every push that you send to us.
So use that if you need it.
Something to note about all of these is that they're only available on development devices.
Your users will not have these switches in most cases and they will almost certainly not have them turned on.
So your web services in production do need to be HTTPS, and they do need to be aware at least of the rate limiting that we do if you're sending a ton of pushes.
So I mentioned that the logging could help you find issues with your web services.
And that will work great for you if you're doing this in a development environment and testing out the first implementation of your server.
But in production we have something else for you.
And this was mentioned briefly in last year's talk about the web service API.
And all it is is a way for you to easily catch issues with your implementation.
If your web service is sending us down things that aren't passes, or if you're sending pushes that don't result in an actual change to the pass, we will tell you.
We will send a message to this URL with logs on the end, and that will let you know that something is happening.
So watch this endpoint.
If you're getting reports from your users of some issues in production, you could make a ton of surveys and ask people "what were you doing when you didn't get this pass updated".
Or, you can just watch this endpoint and find out what's going on from us directly.
So that's really useful.
The most common issue that we've seen and that we do message to this endpoint is people not using the Last-Modified/If-Modified-Since system.
And the way that works again more detail in last year's talk, but I can summarize it is that when you update a pass you can send out a header with a blob of information saying "here is when we last changed this pass".
And then the next request we make will include that header and say "have you changed it since then?"
If the answer is "no", your server sends down an HTTP 304 "nothing changed" and we don't download the pass.
And that saves both your users' batteries and cellular usage, and it saves your server resources.
So: use that.
It's kind of nice.
So let's review all this.
First, the ecosystem.
Passes are information that can be used in the real world.
They come from your server.
They get into the user's pass library via apps of various descriptions.
They're redeemed or used by scanning the barcode on the pass.
And you can update them using our push mechanism.
What's new with passes?
We have richer pass content.
We have some easier ways to get passes, both APIs and user-facing features.
We have more control over pass relevance, the new beacon API and the new distance restrictions.
And we finally have a couple of things that could help you around the whole using-your-passes experience.
Tips and tricks: use the developer settings.
They have real useful information for you.
And use the logging endpoint because it will help you catch your errors in production which is super useful.
Finally, we have a lot of new APIs, as you've just seen.
We have a couple of new user features that can affect how you integrate with Passbook.
If it matters to you about your pass being on multiple devices: validate them, check the barcodes, because it is way easier for passes to be everywhere now.
And, finally, give us feedback.
You might have noticed that I keep calling things out as "this is from a request we had from developers".
And there's a reason for that, which is that a lot of these ideas are based on requests that we've gotten.
So tell us what you want.
We will listen.
We read every bug that you file.
You can talk to our evangelist, Paul Marcos [phonetic].
There's documentation on developer.apple.com, and we will be in the Apple developer forums.
Finally, there's a couple of new sessions that are related to this.
The What's New in Camera Capture one is actually right now, so you are too late, but you can watch the video later.
That talks about the new AVFoundation code-scanning APIs.
The next talk, Integrating Passbook Into Your Ecosystem, is actually really interesting because it's from the Apple Store app team who developed a really nice integration of Passbook with their gift cards that was based entirely on the API that you guys are using, on the public APIs.
They aren't us, and you can go to their talk to get a really good idea for what Passbook integration looks like in a really large scale, high value system.
So, go to that talk: it is at 3:15.
Finally, the iBeacons API that I mentioned is in CoreLocation.
Thanks for coming.
[ Applause ]