Partner Managed Funding Instruments (PMFI)

The onboarding flow configures an ads.twitter.com account for the Twitter account, which can be managed by the partner through the Ads API, and whose advertising spend is billed to the partner.
 

Partner Initial Set-up

The process to initially set-up a new PMFI Ads API partner takes up to 3-weeks from exchange of required information. The following must be shared with your technical contacts at Twitter, as well as the Twitter contact managing the integration with the partner in order to get the process started:

  • The partner must share their PGP/GPG public key. A shared secret key needs to be exchanged between the Ads API partner and Twitter. This will be used to verify data during the onboarding flow.
  • The app_id or consumer_secret for the Twitter app that will be used for Ads API access. You can view and edit your existing Twitter apps via the app dashboard if you are logged into your Twitter account on developer.twitter.com. If you need to create a Twitter app, you will need to have an approved developer account. Twitter allows one app for production+sandbox and one optional app for sandbox-only access. The Twitter app must be created on a corporate, partner-controlled Twitter handle.
     

Advertiser Onboarding Flow

The advertiser onboarding flow occurs via a web browser in the following way:

  1. The user starts the onboarding flow on the partner’s website and enters the handle they want to onboard.
  2. The partner redirects the user to a URL on ads.twitter.com with a signed payload. This payload contains the partner’s API app_id, the Twitter user_id of the Twitter handle which is to be onboarded and a callback URL and other fields documented below.
  3. The user is asked to sign into ads.twitter.com using the standard twitter.com login page.
  4. Once the user is logged in, the onboarding process is initiated. This step includes ad review, account validation and other checks.
  5. When all onboarding tasks are completed, the user is redirected to the callback URL that was provided by the Ads API partner, with a payload that indicates success or failure. This includes the 3-legged authorization process.
     

Onboarding redirect payload

URL for redirect:

https://ads.twitter.com/link_managed_account

The redirect URL will be called with the following parameters:

Name Type Description
callback_url URL encoded string user will be redirected to this url after the account link process completes, regardless of outcome. See the partner redirect url section for protocol details
client_app_id integer Twitter API client app id, used to identify the managing partner
promotable_user_id integer Twitter user_id of the @handle whose promotions are to be managed by the managing partner. Used to make sure it is the same as the user who logs into ads.twitter.com to complete the linking process
fi_description URL encoded String (max 255 characters) funding instrument name. This will be displayed in the description field in the API when the funding instrument is retrieved. If a funding_instrument description is given, the existing funding_instrument will be paused, and a new managed partner funding instrument will be set up. (if one exists with the same name, nothing will happen)
timezone String, in Area/Location format This will be the timezone used to determine the day to which daily budgets apply, and in which charges will be aggregated
currency ISO 4217 Currency Code Currency that will be used to enter bids, and in which charges will be billed
country ISO 3166-1 alpha 2 Country Code Billing Country for the account
signature URL encoded, base64 encoded binary code, as explained below signature that combines a shared secret and the other parameters to verify authenticity of the call, as well as sanity of the parameters.


Callback URL payload

The base redirect URL is provided using the callback_url parameter on the account link request (see above). The parameters added by ads.twitter.com are:

Name Type Description
status string
OK an account was created, or an existing, eligible account was found.
ACCOUNT_INELIGIBLE if partner specific constraints are not met USER_MISMATCH the Twitter account used to sign into ads.twitter.com was different from the promotable_user_id on the account link request INCOMPLETE_SERVING_BILLING_INFO timezone, currency or country were not specified INVALID_COUNTRY an invalid country value was given INVALID_CURRENCY an invalid currency value was given INVALID_TIMEZONE an invalid timezone value was given
account_id URL encoded string Twitter ads account id of the linked account
funding_instrument_id URL encoded string ID of the active partner managed funding instrument
signature URL encoded, base64 encoded binary code, as explained below Base64 encoded HMAC-SHA1 signature that combines a shared secret and the other parameters to verify authenticity of the call, as well as sanity of the parameters. To make sure the callback url is only valid for the Twitter user_id that the account link process was intended for, the twitter user_id is to be appended to the shared secret (using &) when signing the request.

To make sure the callback URL is only valid for the Twitter user_id that the account link process was intended for, the Twitter user_id is to be appended to the shared secret (using &) when signing the request.
 

Signing the request and callback URLs

In order to ensure that the requests to /link_managed_account and the callback url are valid, the requests need to be signed at the source and verified by the recipient before the recipient takes action on them. Signing the request with a secret that is shared between Twitter and the managing partner ensures that each party only accepts requests sent by the authorized counterpart.

The signature generation algorithm is similar to the one used in OAuth.

Create a signature base string as follows:

  • Convert the HTTP Method to uppercase and set the base string equal to this value.
  • Append the ‘&’ character to the base string.
  • Percent encode the URL (without parameters) and append it to the base string.
  • Append the ‘&’ character to the base string.
  • Append the percent encoded query string, which is built as follows:
  • Percent encode every key and value that will be signed.
  • Sort the list of parameters alphabetically by key.
  • For each key/value pair (and with primary_promotable_user_id for the partner redirect url):
  • Append the percent encoded key to the query string.
  • Append the ‘=’ character to the base string.
  • Append the percent encoded value to the query string.
  • Separate the percent encoded key=value pairs with the ‘&’ character.
  • Use the HMAC-SHA1 algorithm, using the previously exchanged shared secret, as the key, and the base string as the value to generate the signature.
  • Base64 encode the output of Step 2, drop the trailing newline character percent encode the signature generated in Step 3 and add it to the url in a signature parameter
     

Signing examples

Signing a link account request

Url to sign, assuming a GET request:

https://ads.twitter.com/link_managed_account?callback_url=https%3A%2F%2Fmanagingpartner.com%2Flink_account_callback&client_app_id=12345&fi_description=some%20name&promotable_user_id=1

This url has the following parameters:

callback_url = https://managingpartner.com/link_account_callback
client_app_id = 12345
fi_description = some name
promotable_user_id = 1

The base string consisting of http method and url without parameters, steps a - d, looks like:

GET https://ads.twitter.com/link_managed_account

The query string, produced by the substeps of e, looks like:

callback_url=https://managingpartner.com/link_account_callback&client_app_id=12345&fi_description=some name&promotable_user_id=1

Note that the key-value pairs are sorted by key name.

The percent encoded query string looks like:

callback_url%3Dhttps%253A%252F%252Fmanagingpartner.com%252Flink_account_callback%26client_app_id%3D12345%26fi_description%3Dsome%2520name%26promotable_user_id%3D1

The complete base string, combining steps a - d and e:

GET https://ads.twitter.com/link_managed_account&callback_url%3Dhttps%253A%252F%252Fmanagingpartner.com%252Flink_account_callback%26client_app_id%3D12345%26fi_description%3Dsome%2520name%26promotable_user_id%3D1

Using the hmac-sha1 algorithm we will sign this with the word “secret” as the key. The result is Base64 encoded, and presented without the final “\n” (steps 2 and 3): KBxQMMSpKRrtg9aw3qxK4fTXvUc=

This signature is then added (percent encoded) to the end of the original url in the signature parameter (step 4):

https://ads.twitter.com/link_managed_account?callback_url=https%3A%2F%2Fmanagingpartner.com%2Flink_account_callback&client_app_id=12345&fi_description=some%20name&promotable_user_id=1&signature=KBxQMMSpKRrtg9aw3qxK4fTXvUc%3D

Signing a partner redirect url (account link request callback) The URL to sign, assuming a GET request:

https://managingpartner.com/link_account_callback?status=OK&account_id=ABC&funding_instrument_id=DEF

This url has the following parameters:

account_id = ABC, funding_instrument_id = DEF and status = OK

The base string consisting of http method and url without parameters, steps a - d, looks like:

GET https%3A%2F%2Fmanagingpartner.com%2Flink_account_callback&``

The query string, produced by the substeps of e, looks like:

account_id=ABC&funding_instrument_id=DEF&status=OK

The percent encoded query string looks like:

account_id%3DABC%26funding_instrument_id%3DDEF%26status%3DOK

The complete base string, combining steps a - d and e:

GET https%3A%2F%2Fmanagingpartner.com%2Flink_account_callback&account_id%3DABC%26funding_instrument_id%3DDEF%26status%3DOK

Using the hmac-sha1 algorithm we will sign this with the word “secret” and the twitter user id for which the original link request was made, 1 (promotable_user_id = 1 from above) as the key, “secret&1”.

The result is Base64 encoded, and presented without the final “\n” (steps 2 and 3): jDSHDkHJIFXpPLVxtA3a9d4bPjM=

This signature is then added (percent encoded) to the end of the original url in the signature parameter (step 4):

https://managingpartner.com/link_account_callback?&status=OK&account_id=ABC&funding_instrument_id=DEF&signature=jDSHDkHJIFXpPLVxtA3a9d4bPjM%3D


Shared Key use / renewal

The signing algorithm should have the ability to repeat itself with multiple keys. This will allow multiple shared keys to be used, and enables cycling shared keys on a periodic basis.
 

partner_managed_funding_instrument creation

If the fi_description parameter is given, and no existing partner_managed_funding_instrument with the same name exists in the account, a new partner_managed_funding_instrument will be created, and all existing partner_managed_funding_instruments will be paused.

If a partner_managed_funding_instrument with the same name exists, no new one will be created.
 

Repeated on-boarding flow calls / token refresh

The on-boarding flow can be repeated in case the API access token was lost. The on-boarding flow implementation will require the user is logged in. If the user matches the promotable_user_id, and the associated ads account is found, and everything looks good, the user will be redirected back to the callback url, and the partner can initiate the OAuth flow to obtain an access token.
 

Non-redirectable error flow

If the account link url is invoked with invalid parameters, the user will be shown a page similar to the one shown in the OAuth flow when invalid or expired parameters are given.
 

Ongoing updates to the PMFI

Once the advertiser has been onboarded, the funding instrument can be managed using the PUT accounts/:account_id/funding_instruments/:funding_instrument_id endpoint by only the partner who manages it.