Skip to main content
Every request to Photon carries an OAuth token in the Authorization header. A token belongs to one organization. There are two kinds:
Machine tokens can’t sign prescriptions. Signing needs the write:prescription permission, which machine tokens can never be given. Your backend can sync patients, draft prescriptions and draft orders, but a signed-in prescriber always signs. That step happens in a browser, with a user token.
That’s why Photon ships Prescribe. It signs the prescriber in, holds their token, and runs the signing and sending, so your frontend never handles a token or calls GraphQL itself. We don’t recommend calling the API directly from a frontend. When you need lower-level control in the browser, use the JavaScript client: it handles sign-in, tokens and the workflow rules for you.

Permissions

read: covers drafting. write: covers the step that commits: changing a patient, signing a prescription, sending an order. A user token carries the permissions of the person’s role. Prescribers have all of them. Other roles, such as medical operations, have everything except write:prescription. A machine token can send an order once a prescriber has signed every prescription on it.

Credentials

Find both kinds in your dashboard under Settings → Developers. See Credentials to create them.
  • Application credentials are a public client_id and a list of allowed URLs. The list must include every domain your app runs on. If you use the iframe, include every domain that shows it, and the Prescribe app’s domain (rx.neutron.health, or rx.new in production). Use them with Prescribe’s React components, the iframe or the JavaScript client.
  • Backend credentials are a client_id and a client_secret. Keep the secret on your server, out of client-side code and version control. The JavaScript client refuses a client_secret in a browser.
Credentials come with every Neutron sandbox account. In production they come with Launch and above. Indie has none, because everything on Indie runs on the prescriber’s own sign-in. If you can’t see them on a paid account, ask your organization’s administrator. Not sure which host and credential a job needs? See Which host and credential.
Deep links need no credentials. They open the Prescribe app, which signs the prescriber in on its own. The iframe needs your Application client_id.

User tokens

With Prescribe, you don’t handle user tokens: Behind each of these, the prescriber signs in at auth.neutron.health with Auth0’s authorization code flow (with PKCE), for the audience https://api.neutron.health, and picks their organization. The token they get can do whatever their role allows, including signing.

Machine tokens

Use a machine token from your backend to sync patients, draft prescriptions and draft orders. Exchange your Backend credentials for one:
Response
A machine token lasts 24 hours (expires_in: 86400). Cache it and request a new one shortly before it expires. Don’t request one for every call.

Calling the API

Send either kind of token as a bearer token to the GraphQL endpoint:
ping is a health check that touches no records. Use it to test a token.

When a token is refused

A missing, invalid or expired token fails the whole request. The response has a top-level errors array and no data:
A valid token that isn’t allowed to do something gets an UnauthorizedError in the mutation’s result. For example, a machine token that tries to sign gets one:
When Photon knows which permission is missing, it names it in requiredPermission. Retrying with the same token gets the same error. See Errors.
Last modified on October 11, 2026