Client Onboarding
Client Onboarding¶
Getting started¶
Here are the first steps for FireFly client onboarding:
Make sure you have an
x-api-key:Find one corresponding to your client here.
If you don’t have an API key, create a trouble ticket and ask the current Devex-API team on-call to create the API key for you.
Complete the authentication.
Set the headers.
Now you’re ready to write queries - see our GraphQL web portal where you can try queries and access documentation for the schema.
When to Use Which Process¶
For client onboarding and API key requests: Use the trouble ticket template
For FireFly feature development: Use the JIRA intake template
Authentication¶
Choose the correct authentication method¶
If you have an ATNA token, which are available to internal Amazon employees, you’re all set to proceed.
If you have an ATZA token, which are available to developers external to Amazon and issued by the Login With Amazon team, utilize this.
If you are internal to Amazon without an ATNA token, you’ll need special approval to get Amazon Identity and Access Management or “IAM” access to our service. Mention this in your trouble ticket.
If you only need to access specific data you may be able to call FireFly anonymously if you provide certain details. See Anonymous Auth.
Authentication steps¶
First Party Auth: ATNA¶
Tip: If you just wish to test a sample ATNA query, you can use this script to generate the Auth header one time. This script is not intended for production.
npx ts-node amu_webapi/tst/utils/GenerateProfileAwareATNAToken.ts
Copy-paste the resulting string into your “Authorization” header, and prepend with “AmznMusic”. For example,
"Authorization": "AmznMusic GENERATED_TOKEN"
Source the Atna token from existing integrations such as MAP.
Create a JSON payload with the signature:
{ "access_token", "deviceId", "deviceType" }Example authentication structure:
{ "access_token": "Atna|EwICIBKjpPxJ3G...", # Atna Token "deviceId": "AB904373C9B947F5...", # DeviceId for resolving Atna Token "deviceType":"A2825..." # DeviceType for resolving Atna Token }If you’re developing on your own you can create a .json file in your terminal.
Utilize Base64 to encode theJSON payload.
a. If you’re developing locally:You should already have base64 installed in your terminal.
Create a .json file containing the authentication payload from the example authentication structure above.
Encode it with the command
cat test.json | base64Use the resulting string as part of the authorization header in subsequent steps. It should look like the following:
ewogICJhY2Nlc3NfdG9rZW4iOiAi...
b. The following is an example of conversion to Base64 in the code:
console.log(Buffer.from( JSON.stringify({ access_token: 'Atna|EwI...', deviceId: 'AB904373C9B947F5...', deviceType: 'A2825...', }) ) );
Provide the encoded string as Authorization header. Use a prefix with the unique code
AmznMusic.Example of Base 64:
ewogICJhY2Nlc3NfdG9rZW4iOiAi...Header Signature:Headers: { "x-api-key" : "amzn1.application.XXX" "Authorization": "AmznMusic ewogICJhY2Nlc3NfdG9rZW4iOiAi..." }
Third Party Auth: Atza¶
Login With Amazon is documented on developer.amazon.com.
For testing and developing changes, use Insomnia or the FireFly developer GraphQL dashboard.
Once your changes are ready for production, provide the Authorization header using the Bearer keyword and the
x-api-keysecurity profile ID from developer.amazon.com.
Example header signature:
Headers: {
"x-api-key" : "amzn1.application.XXX"
"Authorization": "Bearer Atza|IwEBIPz97iea3XQY_H...",
'referral': 'linkfire', // Optional
}
First Party Auth: IAM¶
IAM authentication for Firefly can be accessed specifically from the /dev/internal or /prod/internal endpoint.
For example,[https://XXXXXX.execute-api.us-east-1.amazonaws.com/dev/internal](https://xxxxxx.execute-api.us-east-1.amazonaws.com/dev/internal). IAM currently only supports POST GraphQL requests.
Enable your client to call FireFly with IAM¶
A security profile
x-api-keyfor your client will be needed if one does not already exist.This can be obtained as the MusicFirefly user utilizing the Firefly security profile management documentation.
Or, reach out to the current Devex-API team on-call if you cannot access the MusicFirefly user and/or don’t have a security profile setup for your client.
Within the FireFly CDK repo, ceate IAM dev and prod roles for your feature in the
iamRolefield of your partner application. See the example here, using thecreateServiceIamRolefunction:
const yourClientName = this.createPartnerApplication({
restId,
partnerName: 'AmazonMusic.XXX.XXX',
applicationId: 'amzn1.application.XXX',
rateLimit: 25,
iamRole: this.createServiceIamRole(`your-client-name-${stage}`, stage, region, awsAccountIds[]).roleName,
});
For the
iamRolefield, set the name to include-${stage}at the end. The last parameter ofcreateServiceIamRole,awsAccountIds, is an optional array of AWS account ids you should add to the trust policy of this new role so that it can be assumed for FireFly calls.Your dev role will have permission to hit the NA, EU, and FE dev endpoints, while your prod role will have permission to hit the NA, EU, and FE prod endpoints.
Calling FireFly with IAM auth after setting up your service’s IAM access¶
Use the following required headers:
x-api-key(security profile ID)customer-iddevice-id,device-typemarketormusic-territory
const headers = { 'customer-id': 'yourCustomerId', 'device-id': 'yourDeviceId', 'device-type': 'yourDeviceType', market: 'US', 'x-api-key': 'amzn1.application.XXX', 'profile-id': 'amzn1.actor.person.oid.AF9MXXXX', // Optional };
Use the STS service to assume a role and get your keys as documented in this Knowledge Center article. You will then have an AWS access key and secret key.
If you’re using Insomnia, configure the AWS IAM authentication with your access key and secret key.
Add your GraphQL query to the request, and send using the auth and headers from the previous step.
Anonymous Auth¶
To gain access to anonymous auth for your client or service:
A new security profile specifically for anonymous auth for your client is required — even if an
x-api-keyalready exists for your client for non-anonymous use cases.This can be obtained as the MusicFirefly user utilizing the Firefly security profile management documentation.
Or, reach out to the Devex API team on-call if you cannot access the MusicFirefly user and/or don’t have a security profile setup for your client.
Create a JSON header object containing these required headers:
x-api-key(security profile ID)device-iddevice-typemarketormusic-territoryx-amzn-session-id
Note: Your request headers should not contain an Authorization header. The absence of an Authorization header is how we identify if a request should be validated using Anonymous auth.
Headers: { 'x-api-key' : 'amzn1.application.XXX' 'device-id': 'yourDeviceId', 'device-type': 'yourDeviceType', 'market': 'US', 'x-amzn-session-id': '000-0000000-0000000', }Construct a HTTP request to FireFly with your preferred client with the above headers (and no Authorization header).
Optional headers¶
Features and modifiable behavior¶
The FireFly API allows clients to provide a series of flags under the x-amzn-feature-flags in a comma delimited format to modify resolver or other behavior on the stack.
Currently the API supports the following optional properties for the feature-flag header:
Value |
Description |
Warnings |
|---|---|---|
|
The extensions response will be hydrated with trace metadata indicating how long a query took to resolve alongside where things delayed. |
|
|
The extensions response will be hydrated with complexity metadata indicating the score of the query submitted against the budget for any query. |
Cache Control¶
The FireFly API allows clients to control how clients interface with the various caching strategies at play. Currently the API supports the following optional headers for granular control. They can also be combined within a single header as follows:
"cache-control": "no-cache, no-store"
Header |
Value |
Description |
Warnings |
|---|---|---|---|
|
|
Resolutions will skip retrieval from cache-fleets and resolve directly from providers. |
This behavior will result in higher TPS on upstream services and can contribute to higher latencies. It’s recommended to only provide this header in non-productionized environments or as a workaround until upstream providers can provide mechanisms for event updates. |
|
|
Resolutions from upstream services will not result in persisting state in cache-fleets |
This header will result in other callers not benefiting from previous resolutions. It’s recommended to only provide this header in non-productionized environments or as a workaround until upstream providers can provide mechanisms for event updates. |
MusicTerritory Retargeting¶
Some clients may have a use-case where they do not require customer context but wish to retrieve data from non-contextualized stores, such as music or podcast catalogs, or via search. This API provides clients with the ability to ‘retarget’ a user’s account associated MusicTerritory to view collections in other regions.
Note: Only read operations will work, and results may vary depending on your use case or which upstream API service you call.
Header |
Value |
Description |
|---|---|---|
|
<Any 2 Letter MusicTerritory Code> |
For supported values look at MusicTerritoryUtils |
GraphQL Query best practices¶
See the Insomnia guide to set up this client to test your queries.
API Constraints and Resource Limits¶
The Firefly API has implemented a few safeguards to protect upstream services and encourage healthier query structures from clients.
Request Payload Constraints¶
A constraint has been added to the Query string received by this API. Any request query with a character limit of 4096 or more will be invalidated and the service will return a 413 Large Payload error. If you are encountering this error, it indicates you may be attempting to achieve too much in a single call and should break up the request into multiple calls. Other implications of a large payload like this would be higher latency and stress on upstream providers.
Node Resource Limit (Query Entity Hydration Limit)¶
This constraint enforces the API to not hydrate more than 300 entities of a specific type within a single query. This constraint is placed to encourage users streamlining queries and only requesting nodes necessary for a single call.
For example, with this limit, if a user requests 100 playlists, with 50 tracks, it would equate to:
100 Playlist Entity requests
100*50 = 5000 Track Entity requests
The constraint will result in:
100 Playlists retrieved (with a remainder of 200 for this query)
300 Tracks retrieved
4700 Tracks blocked due to the resource limit constraint
