Legacy Key Sunsetting

This is the biggest question that nearly all of us will have. The notification we received this morning said “We have identified that this app has traffic from legacy API keys.” So the natural next question would either be “which ones” or “from where?” How can a third party identify which apps are using legacy API keys if Keap refuses to provide that information to paying customers?

@David_Blaise this is exact reason we are getting rid of legacy keys. The key is not tied to any 3rd party so we don’t have a way to identify who is calling the API with a given legacy key. The email went out to the owner on record for each tenant that saw usage. I passed along the feedback to include the tenant/s on future email communications. In the mean time when you login into an application you would have also received an in app notification if that app has seen legacy key traffic.

Zapier is not affected by this, so if you received a notification then it is something else making API calls using a legacy key.

To create an API ticket you can go here.

Unfortunately since legacy keys only work with XML/RPC, and they only way to determine what API calls are being made requires us to inspect/log the payloads. We have minimal data around the call like which method is being called, however the vast majority of XML/RPC traffic is DataService.* calls which require us to log the exact params being passed in which we don’t do. So most of the time we don’t have actionable data for this. See my reply to @Mark_Penney as well about the correlation of various logs. This is one of our many frustrations internally about legacy key and XML/RPC usage. If a customer needs insight into the usage they can create an API Support ticket for us to manually piece together some of the puzzle.

I chatted with our PM, and if your question is that you have multiple apps and need to know which ones had legacy API calls I can get that for you. Just message me the email address on file and I can get you the list.

@bradb, any chance you can add a special REST Hook that gets triggered when the Legacy Key has been used?

You have transferred the Legacy Keys across to your Service Account Keys mechanism, so you must have a reference in your database that they are a Legacy Key.

When the API Request comes in, you can identify that it is a Legacy Key, and then trigger the REST Hook of its usage.

This solution is more for developers, but we need something that basically can notify us of the usage of the Legacy Key.

I now have conflicting information from Keap. In the first email we were told no ability to generate new keys after July 10, but now you’re saying that will be possible? This needs to be cleared up for partners and your customers.

I don’t fully follow your response about new apps. If I sell an app on July 11 and the third party apps we want to use have not been updated, are you saying we still have a way to make that work?

Are you saying there is not IP data you can pull for all legacy API calls that can be provided to app owners? There are going to be thousands of custom built and abandoned apps and code out there using this method still. Heck even old Keap Wordpress plugins are still used by some. I’m not a developer or API expert.

The confusion I’m feeling as someone with an understanding of some of this is going to be nothing compared to our clients. I don’t want to alarm clients but with July 10 looming I’m still unsure what is going to happen after that date.

My tech background is infrastructure and I would just hire developers. But I have the ability to understand if it’s explained more clearly. Then I can translate the confusing comms from Keap for my clients and help other partners.

We won’t be doing that. There are many reasons why we can’t do this. Also I am not understanding the reasoning behind these requests. If you are a developer it seems very odd that you want use to send you information on a call you just made. Can you explain this a bit more to help me understand what you are trying to solve?

I now have conflicting information from Keap. In the first email we were told no ability to generate new keys after July 10, but now you’re saying that will be possible? This needs to be cleared up for partners and your customers.

We define the creation of a new key as a tenant that does not already have a legacy key generated they will no be able to generate one. This is true for new apps after July 10th as well since they would not have had a key generated.

I don’t fully follow your response about new apps. If I sell an app on July 11 and the third party apps we want to use have not been updated, are you saying we still have a way to make that work?

You will not have a way to make this work.

Are you saying there is not IP data you can pull for all legacy API calls that can be provided to app owners? There are going to be thousands of custom built and abandoned apps and code out there using this method still. Heck even old Keap Wordpress plugins are still used by some. I’m not a developer or API expert.

We have IP data in access logs, but it is not consumable by customers. Access logs do not have the ability to identify legacy key traffic, but XML/RPC traffic. Also we haven’t seen much value in IP addresses for situations where customers don’t even know they have some custom code or integration running. We know and understand the issues around abandoned code. We feel we have devised a comprehensive plan to communicate this, and to help app owners identify unknown usage. If you haven’t seen our Migration Page, please check it out. If there is still confusion please reach out to us and we can help explain or modify the documentation and future comms.

We define the creation of a new key as a tenant that does not already have a legacy key generated they will no be able to generate one.

That needed to be clarified. How you define it and how it reads were two different things. But I am glad this will still be possible. The original email stated it this way **However, you will not be able to refresh that key or generate a new * Which to me reads the exact opposite of what you are saying. So that needs to be cleared up with customers.

You will not have a way to make this work.

That is going to be the biggest pain point for partners selling new apps. We will have to have answers and solutions in the next couple of weeks to ensure people solutions are not sold that cannot be delivered.

Also we haven’t seen much value in IP addresses for situations where customers don’t even know they have some custom code or integration running.

How do you figure that? As a partner wanting to help all their clients and do the heavy lifting for them, that info would be immensely useful. You seem to just be thinking about direct sales customers perhaps?

Sorry to say that I just cannot rely on and trust in the comms from Keap, I need to be on top of this and make sure my clients don’t get caught out. I know many other partners feel the same way.

@bradb, you are making it very difficult for your customers to know if they are using or have transitioned away from the Legacy Key without giving any direct information if it is still being used.

Some of your customers will have users ranging from 1 to over 100, which means various users over the years may have set up different types of Infusionsoft integrations for their company needs.

As a developer, I know what Legacy Key Integrations I have built for my clients. But I do not know everything in what my client does, which includes what types of Infusionsoft based integrations they would have installed over the years. Some may have been set up years ago, but could have been forgotten about.

The purpose of the REST Hook is to see if there is any activity still going on with the Legacy Key. If I have altered my code to no longer use the Legacy Key, but still get the Hook Responses being triggered, then I can inform my clients that they have other integrations using the Legacy Key.

I was pass this on to the comms team. I will also check with them on what go missed with the ability to rotate legacy keys, so we can correct that portion of the comms.

@bradb, to speed up API support ticket requests, how would you recommend we word things to prevent a lot of back and forth OR having the wrong information.

Plain English: I’d love to see which API calls/services are being used by my legacy API key. With that information, I should be able to reverse engineer which external tools are making those calls and proceed accordingly.

2 Likes

We are not trying to make it difficult. It is just difficult. Please assume good intent and that we doing what we can with what resources we have. This highlights the issue with Legacy Keys in general. We do not have good tracking on usage of these. I am sorry we don’t have great solutions to this. The direct information about usage is being delivered to customers via email and in-app notifications. If their stuff gets migrated then they will no longer receive these comms. I am near 100% sure we will be adding call volume to future comms, based on multiple people requesting this. I know we have this data available already. I am also looking into if it is possible to get additional data in the comms as well. The main issue is the data is sourced from different places and we lose some fidelity as data is rolled up into our reporting. Example what we are using to determine key usage doesn’t contain http request header information. Getting that data in there is not easy and will significantly increases costs.

We understand this and our solution to this is the brownouts, and directed comms to apps that have had legacy key usage.

Ok, I understand what you are trying to solve for. This is not something we can most likely do within a couple weeks regardless, and it only solves for a very small subset of users like yourself. I will see if we can increase the frequency of the in app comms to maybe give a shorter window in which we can isolate legacy key usage.

On a more general note a lot of the complaints and issues that are being raised are well known internally on the development teams that deal with the API. We know it is not ideal, or even passable as a modern API in 2024. We are constantly advocating for our developers in making the developer experience better. We do lack tooling to get developers and customers the data they need. We want a kick ass developer portal. We want users and developers to know exactly what calls are being made. We want better mechanisms to identify and communicate with our developer. We want extreme transparency with customers on who has access to their data. We want autogenerated SDKs in many languages to enable developers, and make transition like this easier. It can be difficult to get this work prioritized. If anyone is a partner please continue to respectfully voice your needs with your partner manager, so the rest of the org/community understands that investing in our APIs, our API tooling, and our API community is time well spent. There is massive value in the API that is unrealized.

I’m having a difficult time trying to make these updates. I know enough php to make myself dangerous but not enough to fully comprehend how to make these changes to the xmlrpc we’ve been using (v3.0 btw).

I’d like to move to the new code and followed the instructions here (GitHub - infusionsoft/infusionsoft-php: PHP client library for the Infusionsoft API.) but I’m still having difficulty connecting properly.

Is there any possibility of providing some more sample code to try and follow?

Thanks for considering!

Could you create a new post with details on what issues you are running into, and I am sure someone should be able to help.

I’m going to post back here in case it helps anyone else.

A couple of observations that might help others. I am not 100% sure of all of this, but it might be worth a look:

  1. Query Monitor plugin was causing me some issues so disabling helped.
  2. I was on PHP 7 which the Keap API did not seem to like. Now on PHP 8.2 I can get connected.

@bradb, thank you for the explanation of things.

I am currently making the required changes to the Legacy iSDK code.

There is a mistake in the Getting Started with OAuth2 Documentation here: Getting Started with OAuth2 - Keap Developer Portal

In the “Refresh Request” section it mentions that “Header:Authorization” should be part of the POST Body Parameter, that is incorrect as it should be in a separate table for sending Headers. I think you should also remove the “Header:” prefix as well.

In the “Making API Requests” section it mentions the “v1” path to the “https://api.infusionsoft.com/crm/xmlrpc/v1” link. The migration guide does not mention this anymore. But it does not matter if you use it, as it gets ignored.

Also, in the past there use to be the “?access_code” URL Parameter, is that discouraged now?

I have refactored the original iSDK to use a customized version of PHPXMLRPC 4.10.3, and I’ve shared the file from my dropbox account.

Everything I tested worked, but I didn’t test everything. I did test on PHP 7.4 and 8.2 and had no errors.

https://www.dropbox.com/scl/fi/qgz413b96lsktkx8q0q9b/isdk-PAT-SAK-Compatible.zip?rlkey=hevuym6ea5v07worugiv1f7ly&st=oqaxu9qd&dl=0

Thank you for the suggestions on documentation improvements Pav, I have incorporated them into that page to assist other developers!

Yes, specifying a key through the URI query parameters is an inherently insecure operation, as URIs are frequently logged in plaintext and may be shared accidentally by end users, so the use of them is discouraged.

@Marion_Dorsett2, nice work in getting an initial version of the Legacy iSDK supported with the changes.

For your reference you can avoid modifying the PHP XML-RPC library by using one of its newer features in setting the cURL HTTP Header. It is not made obvious, but you have to supply the Original Header that it would sent plus the additional header lines, which would be the X-Keap-API-Key or Authorization Bearer.

For the Legacy Key / Service Account Key you can set up the Header as this.

$this->client->setOption('extracurlopts', 
    [ 
        CURLOPT_HTTPHEADER => 
        [
            "Content-Type: text/xml",
            "Accept-Charset: UTF-8,ISO-8859-1,US-ASCII",
            "Expect:",
            "X-Keap-API-Key: {$this->key}"
        ];
    ]
);

For the OAuth Access Token you can set up the Header as this.

$this->client->setOption('extracurlopts', 
    [ 
        CURLOPT_HTTPHEADER => 
        [
            "Content-Type: text/xml",
            "Accept-Charset: UTF-8,ISO-8859-1,US-ASCII",
            "Expect:",
            "Authorization: Bearer {$this->key}"
        ];
    ]
);

@Tom_Scott - Thank you in updating the documentation.

1 Like