How to use Stedi's Search Payers API
Jun 12, 2025
Healthcare
Payer IDs are the routing numbers of healthcare. Every transaction – including eligibility checks and claim submissions – depends on the right one. If the ID is wrong, the transaction fails.
But finding the right payer ID is hard. Payers go by different names. Their IDs change. Most clearinghouses still send out monthly CSVs, which go stale fast. Developers end up maintaining brittle mappings that break every time the list updates.
The Search Payers API fixes that. It lets you search the Stedi Payer Network for payers by name, alias, or ID. You get accurate, up-to-date results in JSON.
You can use it anywhere you need to look up a payer: intake forms, billing tools, internal dashboards, and more.
We use the API in our own Payer Network UI. This post walks through a simplified version of that implementation, using TypeScript and Next.js. You don’t need to be an expert to follow along. If you know basic Node.js and JavaScript, you’ll be fine.
For full details on the Search Payers API, check out the Search Payers API docs.
How it works
We implement search as an API route in Next.js. The front end sends a request when a user types a payer name or applies filters. This route receives search requests from the front end, sends them to the API, and returns cleaned-up payer results in JSON.
Here’s a simplified version of our real implementation. It shows how to handle the request, construct filters, and format the response. It’s not exactly our production code, but it’s close. You can use it as a starting point for integrating the Search Payers API into your own application.
import { NextApiRequest, NextApiResponse } from "next";
import fetch from "node-fetch";
// Stedi API key, pulled from environment variables
const STEDI_API_KEY = process.env["STEDI_API_KEY"]!;
// The Search Payers API endpoint
const STEDI_SEARCH_URL =
"https://healthcare.us.stedi.com/2024-04-01/payers/search";
// The handler for the POST /api/search route
export default async function handler(req: NextApiRequest, res: NextApiResponse) {
// Only allow POST requests
if (req.method !== "POST") {
return res.status(405).json({ message: "Method not allowed" });
}
// Extract values from the request body
const {
query = "*",
pageSize = 100,
pageToken,
eligibilityCheck,
claimStatus,
claimPayment,
professionalClaimSubmission,
institutionalClaimSubmission,
dentalClaimSubmission,
coordinationOfBenefits,
unsolicitedClaimAttachment,
} = req.body as SearchPayersInput;
// Build query string parameters
const params = new URLSearchParams({
query, // the payer name, ID, or alias
pageSize: pageSize.toString(), // how many results to return
...(pageToken && { pageToken }), // pagination token, if provided
// transaction support filters
...(eligibilityCheck && { eligibilityCheck }),
...(claimStatus && { claimStatus }),
...(claimPayment && { claimPayment }),
...(professionalClaimSubmission && { professionalClaimSubmission }),
...(institutionalClaimSubmission && { institutionalClaimSubmission }),
...(dentalClaimSubmission && { dentalClaimSubmission }),
...(coordinationOfBenefits && { coordinationOfBenefits }),
...(unsolicitedClaimAttachment && { unsolicitedClaimAttachment }),
});
try {
// Send GET request to the Search Payers API
const response = await fetch(`${STEDI_SEARCH_URL}?${params.toString()}`, {
headers: {
Authorization: STEDI_API_KEY,
},
});
const data = await response.json() as SearchPayersOutput;
const payers = data.items?.map((item) => item.payer) ?? [];
const totalPayers = data.stats?.total ?? 0;
// Return the formatted results and metadata
res.status(200).json({
payers,
totalPayers,
nextPageToken: data.nextPageToken,
});
} catch (err) {
// Log and return a server error if the request fails
console.error("Search error", err);
res.status(500).json({ message: "Error performing search" });
}
}
We've left out the interfaces and enums to save space.
Search by payer name, alias, or ID
You can pass in a payer name, alias, or payer ID. The API supports fuzzy matching on names and aliases, so even partial or slightly misspelled inputs work. For example: AETNA
, ATENA
, and 60054
all return Aetna. Results are ranked by how closely they match the input.
The query
parameter is required by the API. In our UI, it’s optional. If the user doesn’t provide a value, we default to "*"
. This returns all payers, optionally filtered by transaction support. It’s useful for showing initial results or populating a custom dropdown.
Here’s how the query gets extracted and passed:
// Extract values from the request body
const {
query = "*",
pageSize = 100,
pageToken,
eligibilityCheck,
claimStatus,
claimPayment,
professionalClaimSubmission,
institutionalClaimSubmission,
dentalClaimSubmission,
coordinationOfBenefits,
unsolicitedClaimAttachment,
} = req.body as SearchPayersInput;
Filter by transaction type
The Search Payers API supports filters for specific transaction types. You can filter by any combination of the following:
eligibilityCheck
(270/271)claimStatus
(276/277)professionalClaimSubmission
(837P)dentalClaimSubmission
(837D)institutionalClaimSubmission
(837I)claimPayment
(835 ERA)coordinationOfBenefits
(270/271 COB check)
Each filter accepts one of the following values:
SUPPORTED
– The payer supports the transaction type.ENROLLMENT_REQUIRED
– The payer supports the transaction type but requires transaction enrollment.EITHER
– Includes bothSUPPORTED
andENROLLMENT_REQUIRED
.NOT_SUPPORTED
– The payer doesn’t support the transaction type.
Here’s how the filters are added to the query string:
const params = new URLSearchParams({
query,
pageSize: pageSize.toString(),
...(eligibilityCheck && { eligibilityCheck }),
...(claimStatus && { claimStatus }),
...(claimPayment && { claimPayment }),
...(professionalClaimSubmission && { professionalClaimSubmission }),
...(institutionalClaimSubmission && { institutionalClaimSubmission }),
...(dentalClaimSubmission && { dentalClaimSubmission }),
...(coordinationOfBenefits && { coordinationOfBenefits }),
...(unsolicitedClaimAttachment && { unsolicitedClaimAttachment }),
});
This setup lets you filter for exactly the payers your app can work with and ignore everything else.
Pagination
The Search Payers API returns a maximum of 100 results per request. If there are more results, the response includes a nextPageToken
.
You can pass that token in your next request to fetch the next page. For example:
const response = await fetch(
`${STEDI_SEARCH_URL}?query=blue+cross&pageToken=${nextPageToken}`,
{ headers: { Authorization: STEDI_API_KEY } }
);
This approach avoids offset-based pagination. You don’t need to track indices or compute limits. Just pass the token forward.
In your handler, you can return the nextPageToken
like this:
res.status(200).json({
payers,
totalPayers,
nextPageToken: data.nextPageToken,
});
If nextPageToken
is undefined, you’ve reached the end of the results.
Format results for the UI
The API response includes detailed records for each matching payer. Each result includes:
stediId
– A unique, immutable payer ID you can use in transactions with StedidisplayName
– The payer’s nameprimaryPayerId
–The most commonly used payer IDaliases
– Other payer IDs or names associated with this payertransactionSupport
– Which transaction types the payer supportsenrollment
– Whether transaction enrollment is required, and how it works
Here’s how you might extract the data you need:
const payers = data.items?.map((item) => item.payer) ?? [];
This keeps the front end simple. If you need more data – like aliases, enrollment type, or COB support – you can include it as needed.
Tips
Here are a few tips to help get you started with your own implementation of the Search Payers API.
Multiple filters use AND
logic.
If you pass multiple transaction filters, the API only returns payers that match all of them.
The Search Payers API is designed for routing, not patients.
The payer names and aliases are optimized for clearinghouse routing – not for display. If you need a patient-facing dropdown, build your own list and map to stediId.
Try it yourself
The Search Payers API is available on all paid Stedi plans.
To get started, contact us. We’ll help you set up a proof of concept and walk you through the integration.
Payer IDs are the routing numbers of healthcare. Every transaction – including eligibility checks and claim submissions – depends on the right one. If the ID is wrong, the transaction fails.
But finding the right payer ID is hard. Payers go by different names. Their IDs change. Most clearinghouses still send out monthly CSVs, which go stale fast. Developers end up maintaining brittle mappings that break every time the list updates.
The Search Payers API fixes that. It lets you search the Stedi Payer Network for payers by name, alias, or ID. You get accurate, up-to-date results in JSON.
You can use it anywhere you need to look up a payer: intake forms, billing tools, internal dashboards, and more.
We use the API in our own Payer Network UI. This post walks through a simplified version of that implementation, using TypeScript and Next.js. You don’t need to be an expert to follow along. If you know basic Node.js and JavaScript, you’ll be fine.
For full details on the Search Payers API, check out the Search Payers API docs.
How it works
We implement search as an API route in Next.js. The front end sends a request when a user types a payer name or applies filters. This route receives search requests from the front end, sends them to the API, and returns cleaned-up payer results in JSON.
Here’s a simplified version of our real implementation. It shows how to handle the request, construct filters, and format the response. It’s not exactly our production code, but it’s close. You can use it as a starting point for integrating the Search Payers API into your own application.
import { NextApiRequest, NextApiResponse } from "next";
import fetch from "node-fetch";
// Stedi API key, pulled from environment variables
const STEDI_API_KEY = process.env["STEDI_API_KEY"]!;
// The Search Payers API endpoint
const STEDI_SEARCH_URL =
"https://healthcare.us.stedi.com/2024-04-01/payers/search";
// The handler for the POST /api/search route
export default async function handler(req: NextApiRequest, res: NextApiResponse) {
// Only allow POST requests
if (req.method !== "POST") {
return res.status(405).json({ message: "Method not allowed" });
}
// Extract values from the request body
const {
query = "*",
pageSize = 100,
pageToken,
eligibilityCheck,
claimStatus,
claimPayment,
professionalClaimSubmission,
institutionalClaimSubmission,
dentalClaimSubmission,
coordinationOfBenefits,
unsolicitedClaimAttachment,
} = req.body as SearchPayersInput;
// Build query string parameters
const params = new URLSearchParams({
query, // the payer name, ID, or alias
pageSize: pageSize.toString(), // how many results to return
...(pageToken && { pageToken }), // pagination token, if provided
// transaction support filters
...(eligibilityCheck && { eligibilityCheck }),
...(claimStatus && { claimStatus }),
...(claimPayment && { claimPayment }),
...(professionalClaimSubmission && { professionalClaimSubmission }),
...(institutionalClaimSubmission && { institutionalClaimSubmission }),
...(dentalClaimSubmission && { dentalClaimSubmission }),
...(coordinationOfBenefits && { coordinationOfBenefits }),
...(unsolicitedClaimAttachment && { unsolicitedClaimAttachment }),
});
try {
// Send GET request to the Search Payers API
const response = await fetch(`${STEDI_SEARCH_URL}?${params.toString()}`, {
headers: {
Authorization: STEDI_API_KEY,
},
});
const data = await response.json() as SearchPayersOutput;
const payers = data.items?.map((item) => item.payer) ?? [];
const totalPayers = data.stats?.total ?? 0;
// Return the formatted results and metadata
res.status(200).json({
payers,
totalPayers,
nextPageToken: data.nextPageToken,
});
} catch (err) {
// Log and return a server error if the request fails
console.error("Search error", err);
res.status(500).json({ message: "Error performing search" });
}
}
We've left out the interfaces and enums to save space.
Search by payer name, alias, or ID
You can pass in a payer name, alias, or payer ID. The API supports fuzzy matching on names and aliases, so even partial or slightly misspelled inputs work. For example: AETNA
, ATENA
, and 60054
all return Aetna. Results are ranked by how closely they match the input.
The query
parameter is required by the API. In our UI, it’s optional. If the user doesn’t provide a value, we default to "*"
. This returns all payers, optionally filtered by transaction support. It’s useful for showing initial results or populating a custom dropdown.
Here’s how the query gets extracted and passed:
// Extract values from the request body
const {
query = "*",
pageSize = 100,
pageToken,
eligibilityCheck,
claimStatus,
claimPayment,
professionalClaimSubmission,
institutionalClaimSubmission,
dentalClaimSubmission,
coordinationOfBenefits,
unsolicitedClaimAttachment,
} = req.body as SearchPayersInput;
Filter by transaction type
The Search Payers API supports filters for specific transaction types. You can filter by any combination of the following:
eligibilityCheck
(270/271)claimStatus
(276/277)professionalClaimSubmission
(837P)dentalClaimSubmission
(837D)institutionalClaimSubmission
(837I)claimPayment
(835 ERA)coordinationOfBenefits
(270/271 COB check)
Each filter accepts one of the following values:
SUPPORTED
– The payer supports the transaction type.ENROLLMENT_REQUIRED
– The payer supports the transaction type but requires transaction enrollment.EITHER
– Includes bothSUPPORTED
andENROLLMENT_REQUIRED
.NOT_SUPPORTED
– The payer doesn’t support the transaction type.
Here’s how the filters are added to the query string:
const params = new URLSearchParams({
query,
pageSize: pageSize.toString(),
...(eligibilityCheck && { eligibilityCheck }),
...(claimStatus && { claimStatus }),
...(claimPayment && { claimPayment }),
...(professionalClaimSubmission && { professionalClaimSubmission }),
...(institutionalClaimSubmission && { institutionalClaimSubmission }),
...(dentalClaimSubmission && { dentalClaimSubmission }),
...(coordinationOfBenefits && { coordinationOfBenefits }),
...(unsolicitedClaimAttachment && { unsolicitedClaimAttachment }),
});
This setup lets you filter for exactly the payers your app can work with and ignore everything else.
Pagination
The Search Payers API returns a maximum of 100 results per request. If there are more results, the response includes a nextPageToken
.
You can pass that token in your next request to fetch the next page. For example:
const response = await fetch(
`${STEDI_SEARCH_URL}?query=blue+cross&pageToken=${nextPageToken}`,
{ headers: { Authorization: STEDI_API_KEY } }
);
This approach avoids offset-based pagination. You don’t need to track indices or compute limits. Just pass the token forward.
In your handler, you can return the nextPageToken
like this:
res.status(200).json({
payers,
totalPayers,
nextPageToken: data.nextPageToken,
});
If nextPageToken
is undefined, you’ve reached the end of the results.
Format results for the UI
The API response includes detailed records for each matching payer. Each result includes:
stediId
– A unique, immutable payer ID you can use in transactions with StedidisplayName
– The payer’s nameprimaryPayerId
–The most commonly used payer IDaliases
– Other payer IDs or names associated with this payertransactionSupport
– Which transaction types the payer supportsenrollment
– Whether transaction enrollment is required, and how it works
Here’s how you might extract the data you need:
const payers = data.items?.map((item) => item.payer) ?? [];
This keeps the front end simple. If you need more data – like aliases, enrollment type, or COB support – you can include it as needed.
Tips
Here are a few tips to help get you started with your own implementation of the Search Payers API.
Multiple filters use AND
logic.
If you pass multiple transaction filters, the API only returns payers that match all of them.
The Search Payers API is designed for routing, not patients.
The payer names and aliases are optimized for clearinghouse routing – not for display. If you need a patient-facing dropdown, build your own list and map to stediId.
Try it yourself
The Search Payers API is available on all paid Stedi plans.
To get started, contact us. We’ll help you set up a proof of concept and walk you through the integration.
Payer IDs are the routing numbers of healthcare. Every transaction – including eligibility checks and claim submissions – depends on the right one. If the ID is wrong, the transaction fails.
But finding the right payer ID is hard. Payers go by different names. Their IDs change. Most clearinghouses still send out monthly CSVs, which go stale fast. Developers end up maintaining brittle mappings that break every time the list updates.
The Search Payers API fixes that. It lets you search the Stedi Payer Network for payers by name, alias, or ID. You get accurate, up-to-date results in JSON.
You can use it anywhere you need to look up a payer: intake forms, billing tools, internal dashboards, and more.
We use the API in our own Payer Network UI. This post walks through a simplified version of that implementation, using TypeScript and Next.js. You don’t need to be an expert to follow along. If you know basic Node.js and JavaScript, you’ll be fine.
For full details on the Search Payers API, check out the Search Payers API docs.
How it works
We implement search as an API route in Next.js. The front end sends a request when a user types a payer name or applies filters. This route receives search requests from the front end, sends them to the API, and returns cleaned-up payer results in JSON.
Here’s a simplified version of our real implementation. It shows how to handle the request, construct filters, and format the response. It’s not exactly our production code, but it’s close. You can use it as a starting point for integrating the Search Payers API into your own application.
import { NextApiRequest, NextApiResponse } from "next";
import fetch from "node-fetch";
// Stedi API key, pulled from environment variables
const STEDI_API_KEY = process.env["STEDI_API_KEY"]!;
// The Search Payers API endpoint
const STEDI_SEARCH_URL =
"https://healthcare.us.stedi.com/2024-04-01/payers/search";
// The handler for the POST /api/search route
export default async function handler(req: NextApiRequest, res: NextApiResponse) {
// Only allow POST requests
if (req.method !== "POST") {
return res.status(405).json({ message: "Method not allowed" });
}
// Extract values from the request body
const {
query = "*",
pageSize = 100,
pageToken,
eligibilityCheck,
claimStatus,
claimPayment,
professionalClaimSubmission,
institutionalClaimSubmission,
dentalClaimSubmission,
coordinationOfBenefits,
unsolicitedClaimAttachment,
} = req.body as SearchPayersInput;
// Build query string parameters
const params = new URLSearchParams({
query, // the payer name, ID, or alias
pageSize: pageSize.toString(), // how many results to return
...(pageToken && { pageToken }), // pagination token, if provided
// transaction support filters
...(eligibilityCheck && { eligibilityCheck }),
...(claimStatus && { claimStatus }),
...(claimPayment && { claimPayment }),
...(professionalClaimSubmission && { professionalClaimSubmission }),
...(institutionalClaimSubmission && { institutionalClaimSubmission }),
...(dentalClaimSubmission && { dentalClaimSubmission }),
...(coordinationOfBenefits && { coordinationOfBenefits }),
...(unsolicitedClaimAttachment && { unsolicitedClaimAttachment }),
});
try {
// Send GET request to the Search Payers API
const response = await fetch(`${STEDI_SEARCH_URL}?${params.toString()}`, {
headers: {
Authorization: STEDI_API_KEY,
},
});
const data = await response.json() as SearchPayersOutput;
const payers = data.items?.map((item) => item.payer) ?? [];
const totalPayers = data.stats?.total ?? 0;
// Return the formatted results and metadata
res.status(200).json({
payers,
totalPayers,
nextPageToken: data.nextPageToken,
});
} catch (err) {
// Log and return a server error if the request fails
console.error("Search error", err);
res.status(500).json({ message: "Error performing search" });
}
}
We've left out the interfaces and enums to save space.
Search by payer name, alias, or ID
You can pass in a payer name, alias, or payer ID. The API supports fuzzy matching on names and aliases, so even partial or slightly misspelled inputs work. For example: AETNA
, ATENA
, and 60054
all return Aetna. Results are ranked by how closely they match the input.
The query
parameter is required by the API. In our UI, it’s optional. If the user doesn’t provide a value, we default to "*"
. This returns all payers, optionally filtered by transaction support. It’s useful for showing initial results or populating a custom dropdown.
Here’s how the query gets extracted and passed:
// Extract values from the request body
const {
query = "*",
pageSize = 100,
pageToken,
eligibilityCheck,
claimStatus,
claimPayment,
professionalClaimSubmission,
institutionalClaimSubmission,
dentalClaimSubmission,
coordinationOfBenefits,
unsolicitedClaimAttachment,
} = req.body as SearchPayersInput;
Filter by transaction type
The Search Payers API supports filters for specific transaction types. You can filter by any combination of the following:
eligibilityCheck
(270/271)claimStatus
(276/277)professionalClaimSubmission
(837P)dentalClaimSubmission
(837D)institutionalClaimSubmission
(837I)claimPayment
(835 ERA)coordinationOfBenefits
(270/271 COB check)
Each filter accepts one of the following values:
SUPPORTED
– The payer supports the transaction type.ENROLLMENT_REQUIRED
– The payer supports the transaction type but requires transaction enrollment.EITHER
– Includes bothSUPPORTED
andENROLLMENT_REQUIRED
.NOT_SUPPORTED
– The payer doesn’t support the transaction type.
Here’s how the filters are added to the query string:
const params = new URLSearchParams({
query,
pageSize: pageSize.toString(),
...(eligibilityCheck && { eligibilityCheck }),
...(claimStatus && { claimStatus }),
...(claimPayment && { claimPayment }),
...(professionalClaimSubmission && { professionalClaimSubmission }),
...(institutionalClaimSubmission && { institutionalClaimSubmission }),
...(dentalClaimSubmission && { dentalClaimSubmission }),
...(coordinationOfBenefits && { coordinationOfBenefits }),
...(unsolicitedClaimAttachment && { unsolicitedClaimAttachment }),
});
This setup lets you filter for exactly the payers your app can work with and ignore everything else.
Pagination
The Search Payers API returns a maximum of 100 results per request. If there are more results, the response includes a nextPageToken
.
You can pass that token in your next request to fetch the next page. For example:
const response = await fetch(
`${STEDI_SEARCH_URL}?query=blue+cross&pageToken=${nextPageToken}`,
{ headers: { Authorization: STEDI_API_KEY } }
);
This approach avoids offset-based pagination. You don’t need to track indices or compute limits. Just pass the token forward.
In your handler, you can return the nextPageToken
like this:
res.status(200).json({
payers,
totalPayers,
nextPageToken: data.nextPageToken,
});
If nextPageToken
is undefined, you’ve reached the end of the results.
Format results for the UI
The API response includes detailed records for each matching payer. Each result includes:
stediId
– A unique, immutable payer ID you can use in transactions with StedidisplayName
– The payer’s nameprimaryPayerId
–The most commonly used payer IDaliases
– Other payer IDs or names associated with this payertransactionSupport
– Which transaction types the payer supportsenrollment
– Whether transaction enrollment is required, and how it works
Here’s how you might extract the data you need:
const payers = data.items?.map((item) => item.payer) ?? [];
This keeps the front end simple. If you need more data – like aliases, enrollment type, or COB support – you can include it as needed.
Tips
Here are a few tips to help get you started with your own implementation of the Search Payers API.
Multiple filters use AND
logic.
If you pass multiple transaction filters, the API only returns payers that match all of them.
The Search Payers API is designed for routing, not patients.
The payer names and aliases are optimized for clearinghouse routing – not for display. If you need a patient-facing dropdown, build your own list and map to stediId.
Try it yourself
The Search Payers API is available on all paid Stedi plans.
To get started, contact us. We’ll help you set up a proof of concept and walk you through the integration.
Share
Get started with Stedi
Get started with Stedi
Automate healthcare transactions with developer-friendly APIs that support thousands of payers. Contact us to learn more and speak to the team.
Get updates on what’s new at Stedi
Get updates on what’s new at Stedi
Get updates on what’s new at Stedi
Get updates on what’s new at Stedi
Backed by
Stedi is a registered trademark of Stedi, Inc. All names, logos, and brands of third parties listed on our site are trademarks of their respective owners (including “X12”, which is a trademark of X12 Incorporated). Stedi, Inc. and its products and services are not endorsed by, sponsored by, or affiliated with these third parties. Our use of these names, logos, and brands is for identification purposes only, and does not imply any such endorsement, sponsorship, or affiliation.
Get updates on what’s new at Stedi
Backed by
Stedi is a registered trademark of Stedi, Inc. All names, logos, and brands of third parties listed on our site are trademarks of their respective owners (including “X12”, which is a trademark of X12 Incorporated). Stedi, Inc. and its products and services are not endorsed by, sponsored by, or affiliated with these third parties. Our use of these names, logos, and brands is for identification purposes only, and does not imply any such endorsement, sponsorship, or affiliation.
Get updates on what’s new at Stedi
Backed by
Stedi is a registered trademark of Stedi, Inc. All names, logos, and brands of third parties listed on our site are trademarks of their respective owners (including “X12”, which is a trademark of X12 Incorporated). Stedi, Inc. and its products and services are not endorsed by, sponsored by, or affiliated with these third parties. Our use of these names, logos, and brands is for identification purposes only, and does not imply any such endorsement, sponsorship, or affiliation.