Changelog
What changed in these docs, and in the API they describe.
This page tracks the documentation. The API itself is versioned in its path
(/v2/api-integration-v3) and has not changed version since these docs began.
2026-09: production cases, from real responses
Production cases is a new section: nine situations that break a first integration, each one built from a completed production check rather than from an invented example. The figures are redrawn portal panels, the JSON is the real response body with every identifier replaced by the placeholder for its field.
Corrected against production responses:
tpa_not_configureddoes not reportis_eligible: null. Insideaggregated_resultsit carriesdata.is_eligible: false, which is indistinguishable from a real negative. The advice to tell "we asked and the answer was no" from "we never asked" using that field was wrong. Branch onstatus.delegated_to_search_all_poolis a result status, and it appears on essentially every search-all. It was missing from the enum tables entirely, so a client switching exhaustively onstatushad an unhandled branch on every sweep it ran.all_cardsandis_multi_cardare not emitted by this endpoint. A Daman member holding two packages produces one result carryingcard_indexandmulti_card_total; the other card is not in the body. The multi-card section described a different endpoint's shape.- Which card comes back is not a stable choice. It is whichever result row
was read first, so
card_indexreads 2 on one production check and 1 on the next two, with nothing in the request to explain it. It is not "the primary card", and a client cannot assume it is showing the package the patient is presenting. warning_messages[].message_typeis optional, andwarningis not the severity.message_typetakes"warning"and"information"as documented, but it is present on some entries and absent on others in the same response. Thewarningboolean that looks like the severity flag istrueon every entry in every sample, informational ones included, so it carries nothing. Readmessage_typeand default a missing one to a warning.- The two gatekeeper fields can disagree, and when they do the tri-state is the one that is wrong. The recommendation to prefer it is replaced by taking the union of the tri-state, the boolean and any matching warning.
matched_plan_name, notnetwork, is the field that is routinely null.networkwas null on none of a 4,000-response sample;matched_plan_namewas null on three quarters of it. An integration guarding "unmapped network" is guarding the wrong field.- Build against
copay_details_to_fill, notnew_version_of_copay_analysis. Copay previously pointed at the analysis object, which is the policy's cost sharing before anything resolves it. The numbers to bill against are incopay_details_to_fill, one entry per billing category and one figure per service.copay_analysisis now where that page sends you for the conditions behind a number, for coinsurance, and forspecial_remarks, none of which reach the fill. - The billing categories are
Outpatient,Maternity,SpecializationandInpatient. All four are always emitted, in that order.Inpatientwas missing from the list here andDentalwas documented as universal, which it is not.
New material:
- One response contains four different
visit_typevocabularies, only one of which is the enum you sent. - A benefit's
cost_sharingis an array because one benefit can carry three different rates, separated byapplicable_locationat one payer and by the benefit name at another. - A payer with no credentials on file is reported as
tpa_not_configuredin one check and asfailedin another, with the identical message.
2026-09: maternity_treatment is an ordinary key
Changed in the API:
-
maternity_treatmentis now a key, and a boolean is the shape to build against:{ "extra_args": { "maternity_treatment": true } }The scraper reads the key first and coerces
1/0andyes/no/true/falsein any case. The{"title": "maternity_treatment", "value": "YES"}pair the entry below describes is still accepted and unchanged, so no integration has to move; if you send both, the key wins. New integrations should send the key.This supersedes the correction in the previous entry, which was accurate against the code at the time: the key really was ignored, and answering "Is IP Maternity" No without saying so was a bad enough failure to fix rather than document.
2026-09: the per-payer special cases
The three choices a caller makes are not independent: who you ask, how you name the patient, and what the payer needs on top interact, and the API validates none of it. Every combination returns 200 and creates a task, so the ones that cannot work now say so. Payer-specific requirements collects them on one page, each one openable in the browser, Create a task lists them as worked requests, and the Try it walkthrough names the rules you have walked into as you build the request, including the ones that mean the answer will be empty no matter what.
Removed:
universal-searchanddoctors-mappingare no longer documented here. Both are gated separately from the eligibility endpoints and an eligibility API key does not reach them, so documenting them only invited a 401. If your integration needs either, ask your Mantys contact about appointment access.
Corrected against the code:
-
maternity_treatmentis not a key. It travels as atitleandvaluepair insideextra_args, and there is one such slot per request. This site previously documented it as a key, which is ignored: the payer's "Is IP Maternity" question is then answered No, so the check reports on outpatient maternity cover with no error and no warning. (Superseded: the key is now read, and the pair still works. See the entry above.) -
NAS (
TPA004) and Neuron (TPA001) acceptCARDNUMBERandDHAMEMBERID, not the Emirates ID alone. Both moved onto a shared portal driver that carries all three; the matrix here had not caught up. -
Do not rank search-all matches by
created_at. This site previously told readers to prefer the match with the most recentcreated_atwhen a patient turned up on more than one payer. That field records when that payer responded to the check, not when the policy was issued, so it says nothing about which policy the patient is presenting. Results now says to present every match and let a human choose. -
The clinician field is
doctorId. It carries the clinician's professional licence ID, issued by DHA, Riayati or Shafafiya, never a name someone types out: the licence ID is what the portals match against. This site described it as a name, which is the wrong shape to build against.doctorNameis the original spelling, still accepted and unchanged, and both keys mean the same thing.
Newly documented:
- A search-all accepts any identifier. A member ID or card number sent to
BOTH,DHPOorRIYATIis accepted and the sweep runs. Send the Emirates ID when you have one: it is the only identifier every payer accepts. Daman is never part of a search-all whichever you send. is_member_present_at_the_facility, read by the same two payers and defaulted to true.- Daman does not take
OUTPATIENT. Itsvisit_typeis a service taxonomy, not an inpatient and outpatient split, and two of its values (VALIDITY_CHECK,BABY_FLOW) are separate portal flows rather than visits. Nothing rejects a wrong value at create time, so the task runs and fails at the portal. Every accepted value per Daman entity is now on one page.
Editorial:
- The pages were rewritten for an external reader. Descriptions of internal
machinery gave way to what a caller sends and gets back, limitations are
stated with the action to take, and the pages no longer contradict each other
on whether
/healthneeds headers, whether the API returns 403, or when a search-all is finished. "Special cases" is now Payer-specific requirements. - There is no 403. The authentication page previously promised to tell 401 from 403 and then said no 403 exists. Every credential failure is a 401. Do not fold 400 or 422 into that branch: those mean the request was wrong, not the credentials.
2026-03: v3 documentation launched
First published version of this site. It replaces the internal Notion integration note, which had drifted far enough from the code to be misleading.
Documented: health, create-task, eligibility-result/{task_id},
task-status/{task_id}, universal-search, doctors-mapping.
The documented flow polls eligibility-result, not task-status. The
older note had integrators poll task-status and then fetch the result. That
works, but task-status is a strict subset: it never returns
interim_results, it does not re-sign document links, and its search-all
completion check waits on a payer count the fan-out does not reach. Reading the
handlers side by side also turned up two names for one state, COMPLETE on
task-status against PROCESS_COMPLETE on eligibility-result, which appears
to be an unintended consequence of the Postgres to MongoDB migration.
task-status stays documented on the endpoints page for anyone who meets it in
existing code.
Removed from the documentation:
bulk/create-tasksandget-eligibility-results. Both return 503 on every call: they depend on a database session provider that always raises. They will come back when they work.
Added: a Try it page that walks the flow interactively.
Every response on it is generated in the browser, because a real create-task
signs in to a production insurer portal and handles patient data, so a
documentation page must not be able to start one.
Corrected against the code, where the Notion note was wrong:
- One base URL, not two. The old note carried a second host that belonged to a specific customer.
- One set of auth headers, named consistently. The old note used different header names in different sections.
phoneanddoctorNameare optional. The old note marked them required while showing them empty in every example.- One response envelope per endpoint. The old note showed three incompatible shapes for the same result.
- One schema for
referral_documents, not two. - Copay figures come from samples, not from prose. The old note quoted numbers that contradicted its own example payload.
Removed from published examples: internal identifiers (task_id_in_celery,
job_task_id, his_*, hospital_id, customer-specific approval flags),
parser cache keys, citation fields, and portal usernames that had leaked into
error messages. See Result objects.
Samples are captured from real completed production checks and then scrubbed: patient identifiers, names, phone numbers and document links are replaced with consistent fake values, so a sample reads like a real payload without being one.