n8n logon8n Automation Hub
Debugging notes

The Threads Generate Token Button Gave Me a Token That Expired in About 90 Minutes

Debugging notes · n8n workflow · September 19, 2026

A week earlier I had written down a shortcut for connecting a new Threads account to n8n: skip the OAuth flow, click Generate Token in the app dashboard, get a 60-day token. On the next account the shortcut produced a token that would have died before lunch. What caught it was a habit rather than luck: checking every new token with debug_token before storing it.

Workflow at a glance
  1. Setup for a new brand: a Meta app with the Threads API, the account added as a Threads tester, and the invite accepted from the account's own side
  2. The dashboard's Generate Token button returned a token that looked complete
  3. The debug_token endpoint reported an expiry roughly 1.5 hours away, not 60 days
  4. Exchanging it with the th_exchange_token grant, as Meta's documentation describes, returned the 60-day token, and that one went into the n8n credential
  5. The Facebook Page token needed the same check, with the opposite surprise: it never expires

The shortcut, and where my notes went wrong

The dashboard button is convenient: no redirect URI, no browser flow. My notes from the previous account said it returns a long-lived token directly and that the separate exchange step was optional. On the next setup the button returned a short-lived token. Whether Meta changed the behaviour or my earlier check was too shallow, I can't say. What I can say is that a token that looks fine is indistinguishable from a good one until you ask Meta about it.

Ask the token itself

Threads has a debug endpoint that takes the token as both the input and the credential:

GET https://graph.threads.net/debug_token?input_token=<TOKEN>&access_token=<TOKEN>

The response includes the scopes, the user id and expires_at as a Unix timestamp. Converting that timestamp is the whole test. Mine was about an hour and a half after generation.

The exchange

Meta's Threads documentation describes an exchange call that trades a short-lived user token for a long-lived one, using the th_exchange_token grant type together with the app's secret. Run it from the server, never from a browser or from a workflow that logs its inputs:

GET https://graph.threads.net/access_token?grant_type=th_exchange_token&client_secret=<APP_SECRET>&access_token=<SHORT_LIVED_TOKEN>

The response carries the long-lived token, and debug_token on it showed an expiry about 60 days out. That token went into an n8n HTTP query-auth credential and the short-lived one was discarded.

The Page token had the opposite surprise

For the Facebook Page side I assumed the token from the Page-accounts lookup was also a 60-day token. debug_token said expires_at: 0, which means it doesn't expire. Assuming 60 days would have put a pointless refresh job on the calendar. Assuming "forever" without checking would have been the more expensive mistake in the other direction.

What I do now

  1. Run debug_token on every token before it goes into a credential, and write the expiry date next to it.
  2. Schedule the refresh of a long-lived Threads token before it lapses (Meta documents a refresh call), rather than finding out on day 60 from a failed post.
  3. Keep the app secret out of any node that logs its parameters.

A different Threads failure, unrelated to tokens, is covered in a 500-character limit hiding behind a generic error.

Social API tokens that quietly expire on you?

I set up Meta, YouTube and Threads connections with expiry checks and refresh jobs, so posts don't stop on day 60.