$49 CAD / month

Ontario health card validation in one HTTP request

Check a patient's health card against the Ministry of Health's HCV system before the visit — and skip the SOAP integration, the client certificate and the conformance project entirely.

POST /v1/validate
 curl --request POST 'https://validate2.drtools.ca/v1/validate' \
  --header 'Content-Type: application/json' \
  --header 'Api-Key: YOUR_API_KEY' \
  --data '{
    "MOH_EBS_USERNAME": "your-moh-username",
    "MOH_EBS_PASSWORD": "your-moh-password",
    "provider_number":  "123456",
    "health_number":    "1234567890",
    "version_code":     "AB"
  }' 

That is the whole integration. One HTTPS POST, one Api-Key header, JSON in and JSON out — no SDK, no certificate store, no WS-Security.

The ministry already offers validation.
Getting at it is the problem.

Every Ontario practice has the right to check a health card. The question is what it costs you to actually do it.

Without an API

The IVR telephone line

With Dr. Tools

One HTTPS request

$49 / month
Time per card
Without an APIMinutes, every time
With Dr. ToolsUnder a second — measured at about 0.4s
Cards per check
Without an APIOne
With Dr. ToolsA whole schedule, in one call
Getting the number in
Without an APIKeyed by hand — one wrong digit and the answer is wrong
With Dr. ToolsTaken from the chart — nothing is retyped
Record of the check
Without an APIWhatever the person wrote down
With Dr. ToolsLogged per call, with the ministry's audit id
Fits into your software
Without an APINot at all
With Dr. ToolsEMRs, billing software, booking tools, in-house builds
The bottom line
Without an APIStaff time on every patient, and it never stops costing it
With Dr. ToolsSet up once, then 120 requests a minute without anyone touching it

The ministry's other channels — its SOAP/XML web service and its browser application — are real options, but the first needs a client certificate, WS-Security and a conformance project before you can make one call, and the second is the phone line with a keyboard. We did the SOAP, the certificate and the conformance plumbing once so that you do not have to.

Three different problems,
one endpoint

The pain looks different depending on where you sit. Here is what our Validation API actually changes in each case.

EMR and software vendors

The problem

You have been asked to add health card validation and discovered the ministry's channel is SOAP, client certificates and conformance testing. That is a quarter of a roadmap for one feature.

Our Validation API solves this by:

  • Getting you a first successful call in about 15 minutes — one POST, one Api-Key header, no SDK to adopt
  • Letting you build against every response code up front — the sandbox returns all of them with no ministry round trip
  • Generating your client for you — an OpenAPI schema instead of hand-written request plumbing
  • Publishing the rate limit openly: 120 requests a minute, so capacity planning is arithmetic, not guesswork
  • Absorbing the ministry's changes — when their plumbing moves, it is our problem, not a ticket in your backlog

Clinics and medical practices

The problem

A claim comes back rejected weeks after the visit because the card was expired, cancelled, or the version code was wrong — by which point the patient is long gone and the money is hard to recover.

Our Validation API solves this by:

  • Catching the bad card at check-in, while the patient is still standing in front of you and can do something about it
  • Answering inside the check-in conversation — typically under a second, so nobody waits
  • Returning the cardholder's registered name and date of birth, which catches the card that is valid but belongs to someone else
  • Telling you what the ministry says to do next, in the ministry's own words, on every response
  • Requiring no IT project — your vendor switches it on, or you validate in the browser instead

Billing agencies

The problem

You validate for many providers, at volume. Rejected claims are your margin and your reputation, and reconciling them after the fact is the job nobody wants.

Our Validation API solves this by:

  • Validating a whole schedule in one call — send an array, get results back in the same order
  • Covering every provider from one integration — provider_number travels with each request, not with the account
  • Giving you something to point at in a dispute — per-call logs carrying the ministry's own audit id
  • Handling your volume predictably at 120 requests a minute per account by default
  • Moving the work off the back end — validate tomorrow's bookings overnight instead of reconciling rejections next month

Three steps, then you're done

  1. 1

    Get an API key

    We set your account up and issue your API key. It is shown exactly once — copy it into your secret store, because nobody can retrieve it afterwards, us included.

  2. 2

    Send a request

    POST a health number and version code with your Api-Key header. Pass your MOH credentials per call on /v1, or store them encrypted once and use /v2.

  3. 3

    Read the response

    Branch on status.eligible. The ministry's official response code, description and recommended action are all there when you need the detail.

Your ministry credentials stop living in your app

On the /v2 flow you store your MOH EBS credentials once, encrypted, on your account. Your application then sends only the health card data — the ministry username and password never sit in your application config and never cross the wire again. /v1 remains available if you would rather pass them per call and have nothing stored server-side at all.

Pick a language

It is a plain HTTPS POST, so any language works — the same four fields, four ways.

validate.sh
 curl --request POST 'https://validate2.drtools.ca/v1/validate' \
  --header 'Content-Type: application/json' \
  --header 'Api-Key: YOUR_API_KEY' \
  --data '{
    "MOH_EBS_USERNAME": "your-moh-username",
    "MOH_EBS_PASSWORD": "your-moh-password",
    "provider_number":  "123456",
    "health_number":    "1234567890",
    "version_code":     "AB"
  }' 
validate.js
 const res = await fetch('https://validate2.drtools.ca/v1/validate', {
  method: 'POST',
  headers: {
    'Content-Type': 'application/json',
    'Api-Key': process.env.DRTOOLS_API_KEY,
  },
  body: JSON.stringify({
    provider_number: '123456',
    health_number:   '1234567890',
    version_code:    'AB',
  }),
});

const { results } = await res.json();

// No response-code bands to memorise — the verdict is derived for you.
if (results[0].status.eligible) {
  proceedWithVisit(results[0]);
} 
validate.py
 import os, requests

r = requests.post(
    'https://validate2.drtools.ca/v1/validate',
    headers={'Api-Key': os.environ['DRTOOLS_API_KEY']},
    json={
        'provider_number': '123456',
        'health_number':   '1234567890',
        'version_code':    'AB',
    },
    timeout=10,
)

result = r.json()['results'][0]

if result['status']['eligible']:
    proceed_with_visit(result) 
validate.rb
 require 'net/http'
require 'json'

uri = URI('https://validate2.drtools.ca/v1/validate')
res = Net::HTTP.post(
  uri,
  {
    provider_number: '123456',
    health_number:   '1234567890',
    version_code:    'AB'
  }.to_json,
  'Content-Type' => 'application/json',
  'Api-Key'      => ENV['DRTOOLS_API_KEY']
)

result = JSON.parse(res.body)['results'].first
proceed_with_visit(result) if result['status']['eligible'] 

The ministry's answer,
plus a verdict you can branch on

200 OK
 {
  "results": [
    {
      "response_code": "51",
      "response_id": "IS_ON_ACTIVE_ROSTER",
      "response_description": "Health card passed validation",
      "response_action": "You will receive payment for billable services rendered on this day.",
      "first_name": "JANE",
      "last_name": "DOE",
      "gender": "F",
      "date_of_birth": "1985-04-12",
      "expiry_date": "2029-04-12T00:00:00.000-04:00",
      "health_number": "1234567890",
      "version_code": "AB",
      "response_audit_id": "...",
      "status": { "card": "valid", "eligible": true },
      "duration": 0.435,
      "timestamp": "..."
    }
  ]
} 

status is ours, not the ministry's

We derive { card, eligible } from the official response-code ranges, so your code reads if (result.status.eligible) instead of memorising which numeric bands mean what. Small change, large difference to the person maintaining the integration in two years.

response_audit_id is the ministry's own

Passed straight through, untouched. It is the identifier you want on hand for a dispute or a record-keeping question about a specific transaction.

Demographics come back too

The cardholder's registered first name, last name, gender, date of birth and card expiry — useful for catching the case where the card is valid but belongs to someone other than the person in front of you.

duration is measured, not promised

Every result reports its own end-to-end time including the ministry round trip. Production calls typically come back in well under a second.

Validating more than one card

Send a requests array and receive results in the same order. Useful for validating tomorrow's schedule overnight, or for an agency working across many providers in one pass.

Batch request
 {
  "requests": [
    { "health_number": "1234567890", "version_code": "AB" },
    { "health_number": "9876543210", "version_code": "CD" },
    { "health_number": "5555555555", "version_code": "EF" }
  ]
} 

Built for Ontario healthcare

This is patient data under Ontario health-privacy law. Here is specifically what protects it — not a badge, the actual controls.

Canadian data residency

The service runs in a Toronto data centre. Patient data does not leave Canada in the ordinary operation of the service.

Encrypted in transit and at rest

TLS on every request. Stored ministry credentials are encrypted with Fernet symmetric encryption.

API keys hashed with Argon2id

Never stored in recoverable form. A lost key is replaced, never recovered — including by us.

Health numbers hashed in logs

Health card numbers are HMAC-hashed in audit logs. The trail can prove a validation happened without holding the number in the clear.

Full audit trails

Per-call validation logs, a security event log and a separate administrative action log — three records, three purposes.

Account protection

Per-IP and per-account login rate limiting, automatic IP bans, TOTP two-factor on administrative accounts, strict Content-Security-Policy and per-session CSRF protection.

Hardened infrastructure

Containers run read-only root filesystems with all Linux capabilities dropped and no-new-privileges set. No application port is exposed to the public internet; traffic arrives through a controlled gateway.

High availability

A live standby database in a second location under continuous streaming replication, with a tested one-command failover, plus daily encrypted backups that prune themselves.

Continuous monitoring

Uptime monitoring runs against the validation endpoint continuously.

What we don't claim

These controls are built for the obligations Ontario healthcare providers have under PHIPA. We do not claim an external body has audited or certified them, and no SOC 2 or ISO 27001 audit has been performed — if a vendor tells you otherwise about their own service, ask to see the report.

Dr. Tools is an independent company. It is not affiliated with, endorsed by or certified by the Ontario Ministry of Health. A successful validation reports what the ministry says about eligibility on that day; it is not a guarantee of payment, and claims remain subject to adjudication by the ministry.

One price, published

$49 CAD
per month

Per account, billed monthly from the activation date.

Sign up now
  • Real-time validation against the ministry's HCV system
  • Both integration modes — /v1 stateless and /v2 with stored encrypted credentials
  • Batch validation and time-limited service codes
  • 120 requests per minute, per account
  • Sandbox, live test, key management, request logs and an OpenAPI schema
  • Generated code examples in cURL, Node.js, Python and Ruby
  • Monthly billing; cancel any time

Sign up and we will set the account up with you. Cancelling stops the next renewal and service continues to the end of the period you have paid for. Card payments are processed by Helcim, a Canadian payment processor — Dr. Tools never sees or stores card numbers, only a tokenized reference. You will need your own Ministry of Health EBS credentials; obtaining those is a ministry process on your side and can take time.

What comes with the account

Sandbox

Mock responses covering every ministry response code, with no round trip to the ministry. Write your error handling before you have a single real health card.

Live Test

Run one real validation from the browser and see exactly what your integration would receive back, before you write a line of code against it.

API key management

Create, label, rename and revoke keys. Keys are hashed with Argon2id and displayed exactly once — never retrievable afterwards, including by us.

Code examples for your account

Copy-paste cURL, Node.js, Python and Ruby generated against your own account, plus an OpenAPI schema for generating a client in anything else.

Validation logs

Every call, searchable, with the ministry response attached — including the ministry audit id you need when a claim is disputed.

Encrypted credential storage

Store your MOH credentials once, encrypted, and your application stops carrying them. This is the v2 flow, and it is a real reduction in what your app has to protect.

Batch validation

Send a requests array, receive results in the same order. Validate tomorrow’s whole schedule in one call instead of one round trip per patient.

Time-limited service codes

An optional fee_service_codes array returns fee_service_details per code — for optometry and other specialties with time-limited service eligibility rules.

Monthly billing

Billing is monthly and set up with you. Payments are processed by Helcim, a Canadian processor — we never see or store card numbers.

Technology

HTTPS + JSONRESTApi-Key authBatch requestsOpenAPI schemaSandboxToronto data centreMOH HCV / EBS

OHIP Validation API questions

Do I need my own MOH EBS credentials?

Yes. You use your existing Ministry of Health EBS credentials with the API. Getting those credentials is a ministry process on your side and can take time; activation of your Dr. Tools account is immediate once you have them.

How fast is a validation?

Typically under a second, including the round trip to the ministry. Production calls have been measured at roughly 0.4 seconds end to end, and every response carries its own duration so you can see exactly what your integration experienced.

Can I validate more than one card at a time?

Yes. Send a requests array and you receive a results array in the same order, so a batch of cards can be validated in a single call — useful for validating tomorrow's schedule overnight, or for billing agencies working across many providers.

What languages or frameworks are supported?

Any of them. It is a plain HTTPS POST with JSON in and JSON out, with a single Api-Key header — no SDK required. We supply ready-to-paste examples in cURL, Node.js, Python and Ruby, and an OpenAPI schema is available for generating clients.

Can I test without using real patient data?

Yes. Your account includes a sandbox that returns realistic responses covering every ministry response code without contacting the ministry at all. You can build and test your error handling before you have a single real health card, and a live test runs one real validation when you are ready.

What is the rate limit?

120 requests per minute per customer by default. If your volume needs more than that, tell us what you are planning and we will talk it through.

Where is patient data stored?

Processing happens in Canada, in a Toronto data centre. Health card numbers are HMAC-hashed in audit logs rather than stored in the clear, so the audit trail can prove a validation happened without retaining the health number itself.

What happens if I lose my API key?

Keys are hashed with Argon2id and displayed exactly once, so nobody can retrieve one afterwards — including us. Create a new key and revoke the old one; both take seconds.

Do I have to put my ministry password in my application?

Not with the v2 flow. Store your MOH credentials once, encrypted, on your Dr. Tools account, and your application then sends only the health card data. Your ministry username and password stop living in your application config and stop crossing the wire on every call. The v1 endpoint, where you pass credentials per request and nothing is stored server-side, remains available if you prefer it.

How much does it cost?

$49 CAD per month. We set the account up with you and it activates immediately. Cancelling stops the next renewal; access continues to the end of the period you have paid for.

Does a successful validation guarantee payment?

No. Validation reports what the ministry says about card validity and eligibility on that day. It is not a payment guarantee — claims remain subject to adjudication by the ministry. What it does reliably prevent is the category of rejection caused by an expired, cancelled or mistyped card.

Stop losing claims to bad cards

Try every response code against the sandbox, then run a real validation when you're ready. $49 CAD a month, cancel any time.

OHIP Validation API $49 CAD / month
Sign up