# API Authentication: Keys, Environments, and Errors Source: https://docs.powerhq.co/authentication Authenticate every PowerHQ API request with your API key: one static secret in the x-api-key header, no OAuth handshake, no token to refresh. Authentication is a single step: put your **API key** in the `x-api-key` header. That is the whole model. There is no OAuth exchange and no token to refresh. ## Your API Key Pass your API key in the `x-api-key` HTTP header on every request. The key is a static secret issued by your PowerHQ representative; treat it like a password and never expose it in client-side code or public repositories. ```bash curl theme={null} curl -s -X POST https://eapi.prod.powerhq.co/graphql \ -H "x-api-key: YOUR_API_KEY" \ -H "Content-Type: application/json" \ -d '{"query": "{ utilities(zipCode: \"75231\") { id name } }"}' ``` ```python Python theme={null} import requests response = requests.post( "https://eapi.prod.powerhq.co/graphql", headers={ "x-api-key": "YOUR_API_KEY", "Content-Type": "application/json", }, json={"query": "{ utilities(zipCode: \"75231\") { id name } }"}, ) data = response.json() print(data) ``` ```javascript Node.js theme={null} const response = await fetch("https://eapi.prod.powerhq.co/graphql", { method: "POST", headers: { "x-api-key": "YOUR_API_KEY", "Content-Type": "application/json", }, body: JSON.stringify({ query: `{ utilities(zipCode: "75231") { id name } }`, }), }); const data = await response.json(); console.log(data); ``` ## Where You Can Call From Anything that can make an HTTPS request and set a header can call the API: * Serverless and edge runtimes with rotating egress IPs (Lambda, Cloudflare Workers, Vercel) * Containers and autoscaling groups whose IPs change on every deploy * CI pipelines and local development machines Because the key is the only credential, keep it server-side. Never ship it in a browser bundle, a mobile app, or a public repository. If you need something a browser can call, put a thin proxy of your own in front of it and keep the key on the proxy. Want to try the API before you have a key at all? The [playground](/playground) runs real queries against production with no key and no signup. ## Environments Both environments enforce the same authentication requirements. Use Certification while you build and test; switch to Production for live customer traffic. | Environment | Endpoint | Intended Use | | ----------------------- | -------------------------------------- | ---------------------------------------- | | Production | `https://eapi.prod.powerhq.co/graphql` | Live traffic serving real customers | | Certification (staging) | `https://eapi.cert.powerhq.co/graphql` | Development, integration testing, and QA | Point your integration at the Certification environment during development. It lets you iterate safely without risking any impact to production data or customer-facing systems. Onboarding asks for the IP addresses your team will be testing from, so we can enable them for the certification checkout flow. Sending them early keeps your first end-to-end test from waiting on us. ## Error Responses ### 403 Forbidden A `403 Forbidden` response means the `x-api-key` header is missing, malformed, or not a valid key for that environment. Check that the header is present, that the key has no stray whitespace, and that you are using the right key for the environment you are calling — staging and production keys are different. ### 400 Bad Request A `400 Bad Request` response indicates a malformed HTTP request body — for example, invalid JSON or a missing `Content-Type: application/json` header. Check that your request body is valid JSON and that the `Content-Type` header is set correctly. ### GraphQL Errors (HTTP 200) GraphQL errors — such as unknown fields, missing required arguments, or resolver-level failures — are returned with an HTTP status of `200`. The response body contains an `errors` array alongside (or instead of) the `data` object: ```json theme={null} { "errors": [ { "message": "Field 'unknownField' doesn't exist on type 'Plan'", "locations": [{ "line": 1, "column": 42 }], "path": ["residentialPlans", 0, "unknownField"] } ] } ``` For a full list of GraphQL error codes and how to handle them, see the [Errors reference](/reference/errors). # Disclosure Documents: EFL, TOS, YRAC, and More by Market Source: https://docs.powerhq.co/concepts/disclosure-documents Every plan's documents[] array contains required regulatory disclosures. Learn which types appear by market and how to surface them correctly in your UI. Every plan returned by the API includes a `documents[]` array containing links to required regulatory disclosure documents. The document types present in the array depend on the market the plan is sold in — a Texas plan carries different required documents than a Pennsylvania plan. Always iterate the full array and surface every entry rather than checking for a specific type by name. ## Document types by market | Market | Required document types | | ------------- | ------------------------------------------- | | Texas | `EFL`, `TOS`, `YRAC` | | Pennsylvania | `CONTRACT_SUMMARY`, `TOS` | | Other markets | Varies — inspect `documents[]` on each plan | Additional document types may appear on any plan regardless of market: `PREPAID_DISCLOSURE_STATEMENT`, `ENVIRONMENTAL_DISCLOSURE`, `ARBITRATION_ADDENDUM`, `COMM_POLICY`, `PAYMENT_TERMS`, and `ENROLLMENT` (a link to the supplier's own enrollment page). Do not assume a specific type is absent just because it is not listed above as required for that market. ## Accessing documents Request the `documents` field on any `residentialPlans` query to retrieve the full set of disclosure links for each plan. ```graphql theme={null} { residentialPlans(zipCode: "77007", monthlyUsage: 1000) { id title documents { type url title } } } ``` The response includes one entry per document associated with the plan: ```json theme={null} { "documents": [ { "type": "EFL", "url": "https://enroll.example-supplier.com/EmailHTML/efl.aspx?RateID=3578&BrandID=3", "title": null }, { "type": "TOS", "url": "https://enroll.example-supplier.com/App_Assets/EnrollmentFiles/TOS.pdf", "title": null }, { "type": "YRAC", "url": "https://enroll.example-supplier.com/App_Assets/EnrollmentFiles/YRAC.pdf", "title": null } ] } ``` **`title` is `null` on production plans today.** Build your display label from `type`, and treat `title` as an override that may start arriving later. A UI that renders `title` directly will show blanks. Note also that the document URLs are the supplier's own, not PowerHQ-hosted, so they can move without notice. Link to them, do not cache or mirror them. ## Display requirements **Disclosure documents must be accessible to the customer whenever a plan is displayed, and they must be presented before the customer proceeds to enrollment.** Do not gate or hide disclosure links behind additional clicks once a plan is visible. Regulators in Texas and other deregulated markets require customers to have access to documents such as the EFL and TOS before signing up for a plan. To meet this requirement in your UI: 1. Fetch `documents { type url title }` for every plan you display. 2. Render a link for **each entry** in the array — do not filter or skip types you don't recognize. 3. Make the links accessible on the plan detail view, not only at checkout. 4. Do not assume any specific document type will be present on a given plan. Always iterate the full `documents[]` array. ## PlanDocument type ```graphql theme={null} type PlanDocument { type: LinkType! # Identifies the document category url: String! # Direct link to the document title: String # Optional human-readable label (may be null) } ``` The `LinkType` enum covers all possible document categories: ```graphql theme={null} enum LinkType { EFL TOS YRAC ENROLLMENT PREPAID_DISCLOSURE_STATEMENT CONTRACT_SUMMARY ENVIRONMENTAL_DISCLOSURE ARBITRATION_ADDENDUM COMM_POLICY PAYMENT_TERMS } ``` `documents[]` can legitimately be empty on some plans. An empty array is not an error — it simply means the supplier has not associated any disclosure documents with that plan in the system. Continue to display the plan normally; just omit the disclosures section of your UI for that plan. # Enrollment URLs, Partner Attribution, and Supplier Links Source: https://docs.powerhq.co/concepts/enrollment Understand the two partner-stamped enrollment URLs on every plan and how attribution works so your conversions are tracked back to your account. Every plan returned by the API includes two partner-stamped enrollment URLs you can hand customers off to when they're ready to sign up. Both URLs are pre-configured with your partner code so conversions attribute to your account automatically. ## Hosted enrollment (enrollmentUrl) `enrollmentUrl` links to a full-page, PowerHQ-hosted enrollment flow. Use this when you want to redirect the customer to a standalone page managed entirely by PowerHQ. Your partner code is embedded in the URL as both the `utm_source` and `ref` query parameters, so every completed enrollment is attributed to you. The hosted flow is the fastest integration path. Drop the URL into a button or link and PowerHQ handles the rest — plan display, customer information collection, and supplier hand-off. ## Headless enrollment (headlessEnrollmentUrl) `headlessEnrollmentUrl` provides an embeddable enrollment flow you can render inside your own UI — for example, inside an iframe or a modal. Like the hosted URL, it is already partner-stamped with your `utm_source` and `ref` values. Use the headless URL when you want customers to complete enrollment without leaving your product's visual context. **Example URL pattern:** ```bash theme={null} https://www.cert.powerhq.co/partner-app.html?utm_source=YOUR_PARTNER_CODE&utm_medium=referral&utm_campaign=partners#/redirect?ftype=RESIDENTIAL_PARTNER&plan_id=7a8c1d9f-f83a-4322-850f-c6939ccf4fb3&zip_code=77002&ref=YOUR_PARTNER_CODE ``` The URL contains: * `utm_source` and `ref` — your partner code for attribution * `utm_campaign` — comes back as `partners`. Replace it with your own value to pass attribution * `plan_id` — the unique plan identifier from the API * `zip_code` — the customer's ZIP code passed through from your query ## Prefilling the enrollment The URLs on a plan start the customer at the beginning of checkout. When you already know something about the customer, [`residentialEnrollmentUrl`](/queries/residential-enrollment-url) and [`businessEnrollmentUrl`](/queries/business-enrollment-url) build a link that carries it, so they do not type it twice. Supply the customer's name and contact details through the `customer` argument, their consumption through `monthlyUsage` (residential) or `annualUsageInkWh` (business), and their service account through `utilityAccountNumber`. Each value you pass appears in the returned link and prefills the matching field at checkout. ### Prefilling the service address The service address is attached through the customer's utility account, not through the address itself. It is a two-step flow. Query [`utilityAccounts`](/queries/utility-accounts) to resolve the customer's service account. Search by `accountNumber` when the customer can give you their ESID, which is the reliable path: ```graphql theme={null} { utilityAccounts(accountNumber: "1008901000158230011100") { accountNumber } } ``` Searching by address works too, but the match is strict: `street` must be spelled the way the utility spelled it, unit included, and `street2` is compared exactly. Prefer the ESID whenever you can get one. Send the `accountNumber` from that result as the `utilityAccountNumber` argument on the enrollment URL query. The URL comes back carrying `prospect_id`, PowerHQ's identifier for that service account, and `state`. Their presence confirms the address is attached. Pass the `accountNumber`, not the account's `id`. `utilityAccounts` returns both, and sending the `v2-` prefixed `id` as `utilityAccountNumber` is accepted but attaches nothing — the link comes back without `prospect_id` and no error is raised. The `address` argument behaves the same way. Only `accountNumber` resolves. ## Supplier enrollment link Some plans include a `LinkType.ENROLLMENT` entry inside the `documents[]` array. This entry points directly to the **supplier's own website** and is not a PowerHQ-hosted flow. The `documents[]` enrollment link is **not** guaranteed to be present on every plan. Do not rely on it as your primary enrollment path. Use `enrollmentUrl` or `headlessEnrollmentUrl` for a consistent, partner-attributed experience. The supplier link is best treated as a fallback or reference only. ## Attribution Your partner code replaces the `YOUR_PARTNER_CODE` placeholder shown in the example URL above. The API returns URLs already stamped with your actual code, so attribution works without you doing anything. To pass your own attribution, set `utm_campaign` on the returned link, the same way you do on a [Drop-in Storefront](/storefront) link. Whatever it holds when the customer converts appears in your daily conversion file and your monthly commission report. Leave the rest of the link as returned. Before presenting any enrollment URL to a customer, make sure all applicable disclosure documents are visible. Customers must have access to plan disclosures before they enroll. See [Disclosure Documents](/concepts/disclosure-documents) for requirements. # Understanding Advertised vs. All-In Electricity Pricing Source: https://docs.powerhq.co/concepts/pricing Learn how advertisedPriceUsdPerKwh and allInRateUsdPerKwh differ across Texas and deregulated markets, and which fields to use when building your UI. Each plan's `rates[]` array returns pricing data at three standard usage tiers — 500, 1,000, and 2,000 kWh per month. At each tier you receive two per-kWh rate fields (`advertisedPriceUsdPerKwh` and `allInRateUsdPerKwh`) plus an estimated monthly bill (`avgMonthlyBillUsd`). What those rates include depends on the market the plan is sold in. ## Texas markets In Texas, both rate fields include TDU (Transmission and Distribution Utility) delivery charges, so either value represents a complete electricity cost for the customer. | Field | What it represents | | -------------------------- | -------------------------------------------------------------------------------------------------------------------------------------------------- | | `advertisedPriceUsdPerKwh` | The supplier's published EFL price at exactly 500, 1,000 or 2,000 kWh a month, with no seasonal adjustment. | | `allInRateUsdPerKwh` | The effective per-kWh cost against the customer's real usage pattern, **seasonalized by default**, and the closest estimate of what they will pay. | `allInRateUsdPerKwh` folds in TDU delivery, bill credits, and any fixed fees, so the customer's total bill is fully represented by this field in Texas. ## All other markets (PA, OH, IL, NJ, and more) In deregulated markets outside Texas, the utility bills delivery charges separately. **Neither rate field includes TDU delivery costs.** | Field | What it represents | | -------------------------- | -------------------------------------------------------------------------------------------------------------------------------------------------- | | `advertisedPriceUsdPerKwh` | The supplier's published EFL price at that benchmark, which outside Texas covers the variable supply rate only and excludes any fixed monthly fee. | | `allInRateUsdPerKwh` | The supply rate plus the plan's fixed monthly fee amortized per kWh — still excludes TDU delivery. | Outside Texas, `allInRateUsdPerKwh` does **not** equal the customer's total bill. The customer's total monthly cost is: **Total bill = all-in supply rate × usage + utility delivery charges** TDU delivery is billed separately by the utility and is not available through this API. ## Which field to use Use `allInRateUsdPerKwh` (and the seasonalized top-level `price` field) whenever you need to show a customer their effective supply cost. The all-in rate folds in bill credits and amortized fixed monthly fees so shoppers can make an apples-to-apples comparison across plans. * **Effective supply cost** → `allInRateUsdPerKwh` or the top-level `price` * **Estimated monthly bill at a specific usage tier** → `avgMonthlyBillUsd` * **The static EFL price at a benchmark, as the supplier publishes it** → `advertisedPriceUsdPerKwh` `advertisedPriceUsdPerKwh` and `allInRateUsdPerKwh` are equal only on plans that have no fixed monthly fees and no bill credits. On any plan with those adjustments the two values will differ. ## Fee breakdown The `feeBreakdown` field on `ResidentialPlan` gives you component-level detail on every fee included in the plan's pricing. Each entry describes the fee type (`FeeType`), when it applies (`FeeApplicability`), and the amount. Use this when you want to surface an itemized breakdown — for example, showing a customer that a plan has a \$9.95 monthly base charge before they enroll. Every residential plan opens its breakdown with an `ENERGY_CHARGE` entry. That is the supplier's raw energy charge in dollars per kWh, before any utility delivery charge is added, and it always carries `applicability: PER_KWH`: ```json theme={null} "feeBreakdown": [ { "feeType": "ENERGY_CHARGE", "amountUsd": 0.1269, "applicability": "PER_KWH", "threshold": null }, { "feeType": "UTILITY_PASS_THRU", "amountUsd": 4.9, "applicability": "MONTHLY", "threshold": null }, { "feeType": "UTILITY_PASS_THRU", "amountUsd": 0.06413, "applicability": "PER_KWH", "threshold": null }, { "feeType": "BASE_CHARGE", "amountUsd": 0.0, "applicability": "MONTHLY", "threshold": null }, { "feeType": "BILL_CREDIT", "amountUsd": 200.0, "applicability": "CREDIT_MONTHLY_ABOVE_USAGE", "threshold": 2000.0 } ] ``` Read `ENERGY_CHARGE` when you want to show the supply rate on its own, separately from delivery. Use `advertisedPriceUsdPerKwh` for the supplier's published EFL price, and `allInRateUsdPerKwh` for what the customer actually pays across the year. Do not add the fee entries together to reconstruct either rate. `advertisedPriceUsdPerKwh` is calculated by the supplier, not derived from this breakdown, and `allInRateUsdPerKwh` is seasonalized across the year rather than computed at a single usage point. The `rates` array already carries both at 500, 1,000 and 2,000 kWh. See the [Types reference](/reference/types) for the full `PlanFee` type definition and the complete `FeeType` and `FeeApplicability` enumerations. ## Rate types The `rateType` field on `ResidentialPlan` tells you the pricing structure of the plan. The four possible values are: | Value | Meaning | | -------------- | --------------------------------------------------------------------------- | | `FIXED` | The per-kWh rate is locked for the contract term. | | `VARIABLE` | The rate can change month-to-month, typically indexed to market conditions. | | `PREPAID` | The customer pays in advance for electricity; no deposit required. | | `SUBSCRIPTION` | A flat monthly fee covers electricity up to a defined usage amount. | ## priceType parameter `priceType` is a **`String`**, not an enum, so the value must be quoted: `priceType: "FLAT"`. An unquoted `priceType: FLAT` is rejected as a validation error. | Value | Behavior | | ---------------- | ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | | `"SEASONALIZED"` | The default, also applied when you omit the argument. Prices the plan against a seasonal usage curve built around your `monthlyUsage`, which is the most accurate estimate of what the customer pays on an annualized basis. | | `"FLAT"` | Prices the plan at the exact `monthlyUsage` value you supply, every month, with no seasonal adjustment. Use it when you want a precise rate at a single static usage level. | `priceType` moves more than the top-level `price`. It also moves every `rates[].allInRateUsdPerKwh` and `rates[].avgMonthlyBillUsd`, even though those rows stay pinned to 500 / 1000 / 2000 kWh. Do not mix a `FLAT` bill estimate with a `SEASONALIZED` rate card — pick one `priceType` for the whole response. Any other string is accepted without error and falls through to the default seasonalized behavior, so a typo will not be reported back to you. ## PlanRate type ```graphql theme={null} type PlanRate { usageKwh: Int! # 500, 1000, or 2000 advertisedPriceUsdPerKwh: Float! allInRateUsdPerKwh: Float! avgMonthlyBillUsd: Float! } ``` # Integrate with PowerHQ Source: https://docs.powerhq.co/index One platform for U.S. retail energy: plans, pricing, enrollment and compliance. Put our Drop-in Storefront on your site, or build your own experience on the Plan Data API. Retail energy is a hard market to enter and an easy one to underestimate. Every supplier has its own contract, its own API, its own enrollment logic. Every state has its own compliance rules. PowerHQ turns all of it into one integration. **You build the experience. We power the infrastructure.** Run real queries against live production data. No key, no signup, no conversation. Put our storefront on your site with no code, or build your own on the API. Compare them side by side. **Building with an AI?** [Every page of these docs as one markdown file](/llms-full.txt). Paste or upload that one file and your assistant has the whole reference. The dropdown at the top of any page copies just that page, or opens it straight in ChatGPT, Claude, Cursor or VS Code. ## What PowerHQ handles for you Behind whichever path you choose, the same platform is doing the hard part. The largest provider network of any platform. One relationship instead of dozens of contracts. Rates and availability updated directly from supplier systems, not scraped or cached. PowerHQ owns the contract, eSign, credit check and fulfillment. **No PII risk on your side.** Licensing and regulatory workflows, state by state, maintained by us. Texas, Pennsylvania, Ohio, Illinois, New Jersey and more. The experience adapts to the customer's market. Both supported by default. Support one or both, your choice. ## What it replaces
**Without PowerHQ** * Negotiate contracts with dozens of suppliers * Integrate outdated, inconsistent supplier APIs * Build enrollment submission logic per provider * Maintain compliance workflows state by state * Carry the security and PII risk yourself * Handle licensing and regulatory exposure
**With PowerHQ** * One live, production integration * The acquisition flow is enabled end to end * PowerHQ-hosted checkout, no PII risk * Full control of your own UX * No cost to you. We pay you. * Live in days or weeks, not months
## Partners across industries If your product already has a relationship with the customer, energy is a natural extension. You know their address, you have their trust, and their electricity bill is one of the largest recurring costs you can help them cut. Earn on every move-in, at the moment the resident is already setting up power and expects to be asked. Cut one more recurring bill for customers who already trust you with the last one. Sell more systems by pairing generation with a plan that pays properly for buyback and time-of-use. Win commercial accounts by quoting real plans at their real annual usage, not a rate card. ## Start here Open the [playground](/playground) and run a real query. Nothing to sign, no key to request. [Compare the two integrations](/integrations) and choose the one that matches how much you want to own. For the API path, the [quickstart](/quickstart) gets you to a working call, then the [query reference](/queries/residential-plans) covers every field. Your partner manager issues keys, reviews your plan display for accuracy, and switches you to production. # Choose your integration Source: https://docs.powerhq.co/integrations The Drop-in Storefront puts our shopping experience on your site in days. The Plan Data API lets you build your own. Compare what you build, what you keep, and what each one costs you. Two ways to put energy shopping in front of your customers, and how to pick without a developer in the room. They differ in one thing: **how much of the shopping experience you want to own, and keep owning.** Everything behind the checkout is identical either way. Same suppliers, same plans, same enrollment, same compliance work. And neither one costs you anything: PowerHQ pays you for the customers you send, not the other way around. **Unless you have a specific reason to build your own interface, start with the Drop-in Storefront.** It puts our shopping experience on your site, under your brand, in days, with nothing for anyone on your side to build. | | Drop-in Storefront Recommended | Plan Data API | | ------------------------------ | --------------------------------------------- | --------------------------- | | **What it is** | Our shopping experience, running on your site | Plan data you build with | | **What you build** | Nothing | Your own shopping interface | | **Developer needed** | No. One line of HTML, pasted once | Yes, and ongoing | | **Where customers shop** | On your site | Inside your product | | **Whose brand** | Yours, with a small Powered by PowerHQ badge | Entirely yours | | **Who keeps it converting** | We do | You do | | **New features** | Appear automatically | You build each one | | **Ongoing maintenance** | None | Yours | | **Time to live** | Days | Weeks, then ongoing | | **Checkout and customer data** | PowerHQ | PowerHQ | | **What it costs you** | Nothing. We pay you. | Nothing. We pay you. | **Looking for something even simpler, or don't have a website?** You can take a plain affiliate link instead. Same shopping experience, same compensation, hosted on PowerHQ rather than embedded in your site, and there is no page required to put it on. Ask your partner manager for one. You are not locked in. Partners commonly launch on the Storefront to prove the channel converts, then move to the API later if energy earns a permanent place in the product. Nothing about starting simple closes a door. ## Drop-in Storefront **Our shopping experience, running on your site, under your brand. We hold the supplier contracts.** Your visitors compare plans, choose one, and complete enrollment without ever leaving your site. To them it is your page. Behind it, it is the same shopping experience we run and refine every day. ### What it actually takes to set up One line of HTML, on the page where you want it, the same way a YouTube video or a Google Map goes on a page. Whoever looks after your website pastes it in once. Nothing to build, nothing to maintain, no developer required on your side. That is the whole technical lift. Most of onboarding is us configuring your branding and your tracking codes, not you doing work. ### Your brand, described honestly Your fonts, your colors, your page, and confirmation emails that go out under your name. PowerHQ stays visible in exactly two places: a small Powered by PowerHQ badge, and the disclosures your state requires. That badge earns its space. At the moment a shopper is deciding whether to hand over an account number, it shows a licensed energy provider stands behind the transaction, which is reassurance you would otherwise have to build from scratch. ### What you get without lifting a finger * **Every market, one embed.** The experience recognizes the customer's market automatically. You do not maintain a version per state. * **Residential and business by default.** Or point a specific placement at just one, so your commercial pages show business plans only. * **Your look.** Your fonts and colors, and customer emails that carry your name. * **A head start when you have one.** If you already know the customer's ZIP code, pass it in and they land straight on their plan results instead of typing it again. ### It gets better without you scheduling anything This is the same shopping experience we run for our own customers, so we are testing and improving it constantly. When we make it better, your storefront gets better. No project, no release to wait for, no work on your end. That is the part that is easy to underrate on day one and hard to ignore a year in. Partners who build their own interface only get an improvement when they build it themselves. **Best when** you want energy live on your own site in days, and the shopping experience is not where you want to spend engineering time. For most partners, that is the whole story. Working with a developer? The [Storefront reference](/storefront) has the full link structure, every parameter, sizing, ZIP pre-loading and the reports you get. Onboarding asks for the IP addresses your team will be testing from so we can enable your test links. Branding, customer types and test links. Typically live in days, not months. ## Plan Data API **You render the plans. We run everything behind checkout.** A single GraphQL endpoint returns residential and business plans for any deregulated ZIP code, with component-level pricing, supplier scores, disclosure documents and a ready-to-use enrollment URL per plan. You build the interface exactly as you want it. When the customer picks a plan, you hand them to the PowerHQ-hosted checkout and we take it from there: contract, eSign, credit, fulfillment. One endpoint, always `POST`, your key in the `x-api-key` header. Ask for exactly the fields you need and get back just those. **Best when** the energy experience has to live natively inside a product you already maintain. You have a product team, a design system, and a reason to rank or filter plans against data you already hold about the customer. It is the right call for software companies making energy a permanent part of what they sell, and it is the one path with no PowerHQ badge anywhere. Worth being clear-eyed about the commitment: the interface is yours to build, and then yours to keep optimizing. Conversion improvements we make to the Storefront do not carry over to an interface you built. Plenty of partners take that trade deliberately. It should be deliberate. Real queries against live production data, right now. Your first working call, then the full query reference. Keys, environments, the plan-display accuracy review, and going live. ## What both paths have in common * **PowerHQ owns the regulated parts.** Supplier contracts, licensing, state-by-state compliance, enrollment operations and customer service. * **Checkout is hosted by PowerHQ**, so payment and personal data never land in your systems. * **Every deregulated market**, residential and business, from one integration. * **You never pay PowerHQ.** No setup fee, no license, no monthly minimum. We pay you for every customer who enrolls, and your rates are set in Exhibit A of your partner agreement. ## Still deciding? The honest shortcut: the Drop-in Storefront is live in days, costs you no engineering time, and is the experience we are actively making better. If it turns out you need to own the interface later, the API is there and nothing you did was wasted. Or see the data first. Open the [playground](/playground) and run a real query against live production data. No key, no signup. It is the same data behind both paths. We will show you a live example on a site like yours before you commit to anything. # PowerHQ Plan Data API: Retail Electricity Data for Partners Source: https://docs.powerhq.co/introduction A single GraphQL API for U.S. retail electricity plans — residential and business pricing, utilities, disclosures, and enrollment for approved partners. The PowerHQ Plan Data API gives you real-time access to U.S. retail electricity data across every deregulated market PowerHQ supports. With a single GraphQL endpoint you can retrieve residential and business plans, component-level pricing, disclosure documents (EFL, TOS, YRAC, and more), utility (TDU) lookups, and enrollment hand-off URLs. Send a query naming exactly the fields you want; the server returns only those fields as JSON — nothing more, nothing less. ## Environments Use the **Certification** environment while you build and test your integration. Switch to **Production** when you're ready to serve live traffic. Both environments require the same authentication credentials. | Environment | Endpoint | | ----------------------- | -------------------------------------- | | Production | `https://eapi.prod.powerhq.co/graphql` | | Certification (staging) | `https://eapi.cert.powerhq.co/graphql` | ## What You Can Query Retrieve available retail electricity plans for a residential address, filtered by ZIP code, utility, monthly usage, and price type. Fetch commercial electricity plans by ZIP code and annual usage, with support for move-in scenarios and custom start dates. Look up the transmission and distribution utility (TDU) that serves a given ZIP code — a required input for plan queries in most markets. Get the earliest available service start date for a ZIP code, accounting for move-in rules and market-specific scheduling windows. Validate and retrieve an existing utility account by account number and service address for both residential and business customers. Pull state-level market information — including regulatory context and available rate types — for residential or business segments. ## Coverage Examples throughout this documentation use Texas ZIP codes (for example, 75231 and 77002), but the same queries work unchanged across all deregulated markets PowerHQ supports — including Pennsylvania (e.g. 19103), Illinois (e.g. 60602), New Jersey (e.g. 07030), Ohio, and others. Plan availability and supported query parameters vary by market; check the per-query reference pages for market-specific notes. Your API key is the only credential. Contact your PowerHQ representative for a key, or run real queries with no key at all in the [playground](/playground). Requests without a valid key are rejected with `403 Forbidden`. # Playground Source: https://docs.powerhq.co/playground Run live GraphQL queries against the PowerHQ Plan Data API. No API key required. ← Back to the docs ``` ### Pre-load a ZIP code If you already collect a ZIP on your site, pass it in and the customer lands straight on plan results for their area instead of typing it again. ``` &zip_code=75035 ``` ### One Storefront, different placements You can run links with different parameters in different parts of your site. Point the link on your commercial pages at `service_type=BUSINESS` and the one on your consumer pages at `service_type=RESIDENTIAL`, and each placement shows only the relevant plans. ## What you get without configuring it * **Every deregulated market, one embed.** The experience recognizes the customer's market automatically. You do not maintain a version per state. * **Residential and business by default.** Restrict a placement with `service_type` when you want to. * **Your brand.** We apply your fonts and colors during setup, and customer emails can be sent under your own sender name rather than PowerHQ. ## Partner codes You get one partner code. If you want to track activity separately by site, channel, campaign group or sub-brand, we can set up a **parent code with child codes underneath it**. Every conversion is reported against the code that produced it, parent or child. Combined with `utm_campaign`, that gives you two independent tracking dimensions. ## Testing Onboarding collects the IP addresses your team will be testing from so we can enable your test links. Sending them early keeps your first run-through from waiting on us. Your live Storefront is open to everyone, as you would expect. Put the iframe on a staging page and run the flow as a customer would. Confirm: Check `width="100%"` behaves on desktop and mobile. Only if you are passing `&zip_code=` from your site. Fonts and colors should read as part of your page, not as a visitor. Per placement, if you are using `service_type`. Your partner code and `utm_campaign` values should appear in the daily conversion file. Once testing passes, your partner manager sends production links with the same structure on the production domain, and you can go live immediately. ## Reporting and attribution You receive three reports. | Report | What it gives you | Cadence | | ----------------------------- | ------------------------------------------------------------------------------------- | -------------- | | **PostHog dashboard** | Funnel and traffic analytics for your Storefront | Near real-time | | **Daily conversion file** | Every conversion with order details, your partner code and the `utm_campaign` value | Daily | | **Monthly commission report** | Every conversion and the payments owed to you, with the same code and campaign fields | Monthly | **Fields in the daily conversion file:** Order ID, Conversion DateTime, Estimated Conversion Value, Customer Name, UTM Campaign, Referral Code, Term Length, Start Date, Annual Usage, Customer Type. Whatever sits in `utm_campaign` at the moment of conversion is what lands in your reports. Partners use it two ways: some pass campaign details directly, others pass a unique ID and match it back to the source in their own systems. Either works. ## Compare with the API The Storefront is the recommended path for most partners. If the energy experience has to live natively inside a product you already maintain, see the [Plan Data API](/introduction) instead, or [compare the two side by side](/integrations).