On August 11, 2026, Notion started strictly enforcing the Bearer prefix in Authorization headers. CF7-to-Notion plugin integrations that were working that morning were broken by that afternoon. Forms started showing errors to visitors. The Notion database list disappeared from the plugin settings. Every API call returned:
401 unauthorized: API token is invalid
The token was not invalid. The integration was not misconfigured. Notion simply changed how strictly it validates the Authorization header format - and the plugin was sending the token without the required Bearer prefix.
This is one of the cleanest and most thoroughly documented bugs I have seen in the WordPress support forums. The developer who filed the report identified the exact line of code, proved the cause with a command-line test, wrote a working workaround, and even flagged a PHP 9 breaking change in the same plugin. The plugin team responded within days with a patch.
The Root Cause: Missing Bearer Prefix in the Authorization Header
HTTP Bearer authentication requires this exact header format:
Authorization: Bearer secret_abc123...
The CF7 Notion addon (version 1.6.2 and earlier) was sending:
Authorization: secret_abc123...
The raw token, no prefix. This is the relevant line from the plugin source at includes/classes/class-api-notion.php:
'Authorization' => $this->secret_token,
Until August 11, Notion's API accepted both formats. After that date, Notion tightened its header parsing and started rejecting the bare token with a 401. The plugin code had not changed. Notion's validation had.
The developer confirmed this with a direct command-line test:
# With correct Bearer prefix — returns 200 OK
curl -H "Authorization: Bearer secret_..." https://api.notion.com/v1/databases
# Without Bearer prefix — returns 401
curl -H "Authorization: secret_..." https://api.notion.com/v1/databases
Same token. Same endpoint. Different header format. Different result.
If You Are on Plugin Version 1.6.2 or Earlier
Update to version 1.6.3 immediately. The plugin team released the fix on August 24, 2026. No settings changes are needed after updating. The plugin adds the Bearer prefix and also includes a guard for tokens that had the prefix manually added via the workaround filter.
If your automatic updates are delayed or you cannot update right now, apply this temporary fix using the WPCode or Code Snippets plugin:
add_filter( 'add-on-cf7-for-notion/notion-api/request-args', function( $args ) {
if (
! empty( $args['headers']['Authorization'] ) &&
0 !== stripos( $args['headers']['Authorization'], 'Bearer ' )
) {
$args['headers']['Authorization'] = 'Bearer ' . $args['headers']['Authorization'];
}
return $args;
} );
Add this as a PHP snippet, activate it, then go to Contact in your WordPress admin and reload the Integration tab. Your Notion databases should reappear immediately.
Once you update to 1.6.3 you can safely remove this filter - the version 1.6.3 patch handles the Bearer prefix natively.
The PHP 9 Breaking Change Also In This Plugin
The same developer identified a second bug in the same code. The get_databases() pagination function contains:
sleep( 0.25 );
sleep() takes an integer argument. Passing 0.25 (a float) silently becomes 0 in PHP 8 - the intended quarter-second throttle never happens. On PHP 8.1+, this logs a deprecation notice:
PHP Deprecated: Implicit conversion from float 0.25 to int loses precision
On PHP 9, this becomes a TypeError - a fatal error that will break database listing entirely. The correct call is:
usleep( 250000 ); // 250,000 microseconds = 0.25 seconds
The plugin team included this fix in version 1.6.3 as well. If you are running PHP 8.1+ you may already see the deprecation notice in your error logs. Updating to 1.6.3 fixes it.
The Broader Lesson: External API Enforcement Changes Break Integrations Silently
This incident is a precise example of a category of failure that is extremely common but almost never anticipated: an external service changes how strictly it validates its API without breaking changes to the response format, and plugins that were previously working break overnight.
Notion did not change its API version. They did not remove an endpoint. They did not change the response format. They just started enforcing an existing requirement more strictly. The plugin's requests had always been technically malformed — they just happened to work until Notion decided to start caring.
This happens with auth headers, content-type headers, API version headers, and rate limiting. The plugin that worked for two years can fail on a Tuesday morning because the receiving service tightened validation on Monday evening.
The only way to know when this happens is to have response logging on every API call. Contact Form to API logs the response from every submission attempt. When Notion started returning 401s, you would have seen it in the log on the first failed submission rather than finding out when a client called to say their form was broken.
Connecting CF7 to Notion Directly
For a more resilient CF7 to Notion integration, you can call Notion's API directly rather than relying on a dedicated plugin.
Notion's API for creating a page (database row):
POST https://api.notion.com/v1/pages
Authorization: Bearer YOUR_NOTION_TOKEN
Content-Type: application/json
Notion-Version: 2022-06-28
{
"parent": { "database_id": "YOUR_DATABASE_ID" },
"properties": {
"Name": {
"title": [{ "text": { "content": "Jane Smith" } }]
},
"Email": {
"email": "jane@example.com"
},
"Phone": {
"phone_number": "1234567890"
}
}
}
Note that Notion requires the Notion-Version header (2022-06-28 is the current stable version). Property names in the payload must exactly match the column names in your Notion database. Property types (title, email, phone_number, rich_text, etc.) must match the column type configured in Notion.
Quick Reference
| Symptom | Cause | Fix |
|---|---|---|
| 401 on all Notion API calls from August 11, 2026 | Plugin sending token without Bearer prefix |
Update to v1.6.3 or apply filter workaround |
Deprecation notices for sleep(0.25) in PHP logs |
sleep() called with float argument |
Update to v1.6.3 (uses usleep(250000) instead) |
| Will break on PHP 9 |
sleep(0.25) becomes TypeError
|
Update to v1.6.3 now |
| Notion databases not appearing in plugin after token entry | Same 401 issue | Same fix as above |
Top comments (0)