# Didit Analytics, Teams and Roles Source: https://docs.didit.me/academy/analytics-teams-roles Video transcript: the operator's guide to Didit analytics dashboards, team management, roles and permissions. Full transcript of **Didit Analytics, Teams and Roles - The Operator's Guide** - Didit Academy video 9 of 10, 06:37. [Watch on YouTube](https://www.youtube.com/watch?v=sRcOBxjRYag). Each paragraph links to the exact moment in the video. ## What this video covers [00:04](https://www.youtube.com/watch?v=sRcOBxjRYag\&t=4s) This video covers two things every operator needs once Didit is live. The first is seeing how your account is actually performing and the second is controlling who on your team can do what. So, on the analytic side, if you're running transaction monitoring, Didit turns all the activity into a live dashboard of numbers that you can act on. Then, we'll move over to the team side where you decide who gets to see and change each part of the account. So, let's dive in. ## Where analytics live [00:36](https://www.youtube.com/watch?v=sRcOBxjRYag\&t=36s) So, the analytics in Didit live in the transactions product. So, we head over to the transactions tab here on the left and we could see at the top we can hit overview, right? So, instead of reading one row at a time, you're reading numbers that you can actually act on. So, if you're only running verifications, you'll spend your time in the sessions list from previous videos, which you can see in the user verifications tab here, or you can see the overview in your dashboard on your home page. You can also add these cards to your home page, but this is ## Date ranges, filters and export [01:13](https://www.youtube.com/watch?v=sRcOBxjRYag\&t=73s) specifically about your transactions. Now, we can actually change the the date range here. We can filter by tag. We can filter by type, so that's fiat, crypto, KYC, gambling, all of those. And we can actually export the the report here. So, that's just going to give you an Excel export that you can do ## Volume, geography and channel split [01:31](https://www.youtube.com/watch?v=sRcOBxjRYag\&t=91s) things with. You can put it into Claude. You can create fancy reports to share with your team. So, the first numbers that you can check out here is volume, so how many transactions run over your time window here, and whether that's trending up or down against the period before. So, you can see there's a breakdown here by the country of the user behind each transaction. We've got the split down here between fiat, crypto, and gambling. So, really you could see at a glance where your activity is concentrated and which side ## Rule analytics and the review trend [02:01](https://www.youtube.com/watch?v=sRcOBxjRYag\&t=121s) of the house it's coming from. Now, we can also see the analytics for our rules. So, you could see which monitoring rules are firing the most and how your approved, declined, and in review mix. So, you see this card right here, this shows your top rules that have been triggered. So, you could see which monitoring rules are firing the most and how your approved, declined, and in review mix is trending over time. [02:25](https://www.youtube.com/watch?v=sRcOBxjRYag\&t=145s) So, a rising in review line is your early warning that more work is about to ## Customizing your home dashboard [02:31](https://www.youtube.com/watch?v=sRcOBxjRYag\&t=151s) land on your analysts. So, you can spot risk forming rather than counting it after the fact. So, this is the best place to go to see your analytics on your transactions and for your verifications, we can customize our home page to show the volume of verifications, IP locations, all of this stuff. And if you want to customize that, we can go to edit and we can move around these tabs if we want and we can also add additional tabs from user verifications and business verifications. You can throw in some transaction data as well if you want if you want everything in one dashboard. [03:08](https://www.youtube.com/watch?v=sRcOBxjRYag\&t=188s) So, let's just switch from measuring to governing and the first thing to ## Organizations [03:12](https://www.youtube.com/watch?v=sRcOBxjRYag\&t=192s) understand is that everything in Didit lives inside an organization. So, that's the account that holds your billing, your people, and your applications. So, you see this switcher down here, you can jump between organizations here. Now, I only have one organization set up, but you could create a separate organization as well. Now, the account ## Account settings and the audit log [03:31](https://www.youtube.com/watch?v=sRcOBxjRYag\&t=211s) settings holds the organizational wide settings. So, your plan, your invoices, an audit log of who did what, which is exactly what you want for compliance and incident review. Now, inside each ## Applications, live and sandbox [03:43](https://www.youtube.com/watch?v=sRcOBxjRYag\&t=223s) organization, you can create multiple applications. So, if I had an additional application here, you know, I can create a new one with this tab, it's going to show up inside of here. We're going to have live and sandbox for each. Now, if you want to switch to sandbox, that's coming soon. It's going to have its own API keys, its own workflows, and its own webhooks for testing. So, let's head over to the ## Team members and roles [04:04](https://www.youtube.com/watch?v=sRcOBxjRYag\&t=244s) settings tab down in manage. We've got our team members in here as well. And each person carries exactly one role. And this is important, right? It's the role, not the person, that decides what they can see and do. You can see here, this is me. And you can see there's no settings cog here. So, I can't accidentally come in here and change my role and lock myself out of my own account. But, if I do click into here from somebody else, I can change them from owner to developer to compliance to admin, all of the different options here. So, ## Inviting a teammate [04:38](https://www.youtube.com/watch?v=sRcOBxjRYag\&t=278s) if I want to add a new team member, just click this tab up here. I can add in their email address and select the applications that they're going to have access to and the different kinds of access that we want to give them. Now, until they accept, you'll see a orange pending badge, which means the invite went out, but the person has no access at all yet. So, every organization comes ## The five built-in roles [05:01](https://www.youtube.com/watch?v=sRcOBxjRYag\&t=301s) with five roles out of the box, and you just match the role to the person. The owner has full access, so including billing, that's usually just you, the owner of the business, or select few people on your team. Admin runs the members, the applications, the workflows, basically everything apart from billing or deleting the organization. We've got compliance officer. This is built for your risk people. So, reviewing verifications, cases, and screening with no developer or billing access at all. Developer covers the APIs, the webhooks, the applications. And the reader down here is read-only on sessions, analytics, and reports, which makes it the safest role for observers and executives who just ## Custom roles [05:41](https://www.youtube.com/watch?v=sRcOBxjRYag\&t=341s) need to look. Now, if none of those roles suit the needs of someone on your team, we can actually create a custom role and define the permissions that we want to give them. And that can be done here. ## Recap [05:54](https://www.youtube.com/watch?v=sRcOBxjRYag\&t=354s) Finally, at the bottom here, we can see how many members have access to the specific role. So, that's the operators view of Didit, an analytics side that shows you how your transaction activity is really performing, and a team side that lets you control exactly who can see and change what. So, between the two, you can measure the business and keep it locked down at the same time. And if you'd rather work with the numbers in your own tools, all of it is available over the API and the MCP. So, head over to didit.me, sign up for free, and invite your first teammate today. # Build a KYC Workflow With No Code Source: https://docs.didit.me/academy/build-kyc-workflow Video transcript: building a KYC verification workflow visually - checks, branching logic, risk rules, testing, and publishing to production. Full transcript of **Build a KYC Verification Workflow With No Code (Full Tutorial)** - Didit Academy video 3 of 10, 18:54. [Watch on YouTube](https://www.youtube.com/watch?v=7-nJ3JE20i4). Each paragraph links to the exact moment in the video. ## What a workflow is [00:03](https://www.youtube.com/watch?v=7-nJ3JE20i4\&t=3s) In this video, we're going to be building a complete verification flow from scratch, and you won't need to write a single line of code. A workflow is really just a recipe for a verification, which checks to run and in what order. Normally, that kind of thing lives with your engineers. But in Didit, you build it yourself visually. You watch the price update as you go, and you push it live whenever you're ready. [00:28](https://www.youtube.com/watch?v=7-nJ3JE20i4\&t=28s) If you want to build one yourself, you can head over to didit.me, sign up for free, and put your first workflow together in just a few minutes. All right, so let's start where every verification flow lives, and that's in ## The workflow list and workflow IDs [00:39](https://www.youtube.com/watch?v=7-nJ3JE20i4\&t=39s) the workflow list underneath the configure tab here. So all of the workflows that we've currently got in this account, you can see the type. We've got KYC and KYB. We've got simple and graph, and we could see all of the different checks and features inside of each workflow. We could see the price spread. So this basically shows the price from somebody who goes through and does one check and doesn't complete versus somebody who completes the entire flow. We have a a link for the workflow. [01:09](https://www.youtube.com/watch?v=7-nJ3JE20i4\&t=69s) We can add a new session manually. We can copy the workflow ID. We can duplicate, rename, archive, all of your usual stuff. And this is your workflow ID here. So multiple versions of the same workflow is just going to run off the same ID. So if you do update the workflow, you don't need to change anything inside of your code or your app. So the simplest way to think about a workflow is that this is just a recipe for a verification. So which checks to run in what order and what rules to follow. So there's two different ## Simple vs graph workflows [01:40](https://www.youtube.com/watch?v=7-nJ3JE20i4\&t=100s) structures like I mentioned. There's simple and there's graph. So a simple flow is just one check or a few checks with no branching at all. No conditional logic. It's quick to set up and it covers most cases. So you pick your modules and you're done. So I mean if we take a look at this example workflow, you can see we can select the modules here over on the left and it's going to sequence them all in order. Now for a ## A graph workflow with branching [02:05](https://www.youtube.com/watch?v=7-nJ3JE20i4\&t=125s) graph-based workflow, if we click into here, we could see there is some branching at the end. So we can get a little bit more granular with where we direct the user through this verification flow. So you can see in this workflow for example there is multiple different branching points. We can include webhook calls as well. Um and in general we can just add a little bit more complexity in here when needed. [02:30](https://www.youtube.com/watch?v=7-nJ3JE20i4\&t=150s) So you just note here as well the KYB workflows look exactly the same but we just have different checks. Okay. So if we want to add a check we can pop in here. We can grab one of the user actions or set up some background checks. These are the ones that the user doesn't see on the front end. So, all ## Creating a new workflow from a template [02:51](https://www.youtube.com/watch?v=7-nJ3JE20i4\&t=171s) you need to do is hit new workflow. Got a couple of options here. KYC, KYB. Let's hit KYC. And we've got simple versus advanced like I showed you earlier. And I'll show you options for both. If we click simple, we have a ton of different templates here for all sorts of different industries. And we can see the cost for each of these templates. We've got age gates. We've got email verification. [03:19](https://www.youtube.com/watch?v=7-nJ3JE20i4\&t=199s) We've got biometric authentication, insurance, healthcare, all of this stuff. Now, for example, if we use a business verification, and we use the advanced version, which is the graph, again, we've got a bunch of different templates or recipes if you want to call them that. So, we could set up high-risk country KYB and boom. You don't even have to click and drag and drop anything in here. It's already built. So every ## Picking a check on each node [03:48](https://www.youtube.com/watch?v=7-nJ3JE20i4\&t=228s) node here has a dropdown. So you can just pick the check that you want. You can change it like here or we can put the registry check. Whatever you want. ID verification, livveness, face match, AML, proof of address. All of the checks that Didit can offer for KYB and KYC are available inside of these nodes right here. So, if I wanted to add an additional check into here, for example, let's say I wanted to do a AML screening, then I can add that into here. We'll get into the rules and these tabs in in just a moment, but you could see in this workflow, I've added that in to this workflow here. So, if you go into a KYC graph workflow here, most of these workflows are going to start with ID verification. It's the most common ## Inside the ID Verification node [04:33](https://www.youtube.com/watch?v=7-nJ3JE20i4\&t=273s) check. And you can see here, this is the ID verification node. We got 500 free checks per month and the same for the livveness and same for the face match. Now, this ID verification does way more than just read text off a card. It proves the document is genuine. checking the security features, looking for tampering, reading the fonts and the layouts, and then it extracts every field, the name, the date of birth, the document number, the expiry, all by OCR in any language across all 14,000 plus supported document types. So, this is never just text. It's an authenticity check first and then data second. So, let's configure one of these modules. ## Liveness modes and what each costs [05:15](https://www.youtube.com/watch?v=7-nJ3JE20i4\&t=315s) Let's I mean, if we head over to the livveness module, you can see we've got a few different livveness modes. We've got passive, which detects livveness using a selfie. We've got flashing, so we confirm the livveness using dynamic light patterns to detect real user faces. Then we've got a 3D action. So, it's going to confirm the lighting with some kind of action, whether it's a blinking of the eyes or a turning of the head. Now you can see for the passive livveness check, we do get 500 free credits a month and then 10 cents per check while the flashing and the 3D action is 15 cents per check. And we don't get any free checks included in our free account. So in the rules tab, ## Rules: thresholds, duplicate faces, multiple faces [05:56](https://www.youtube.com/watch?v=7-nJ3JE20i4\&t=356s) this is how we decide whether the module is required or optional. So if we head over to the rules tab, we can see there's a few different options here. So this allows us to configure the sensitivity of the testing. So we can set a tolerance level. If somebody has a livveness score of less than 70, then it's going to send them to in review. And we can we can change that if we want. And it's the same for decline. We can also have a setting for a duplicated face. So when a user's face matches one from a previously approved session, how do we proceed? So approve, review, or decline. And then we can customize the similarity threshold by ethnicity. So we can set the duplicate detection sensitivity depending on their ethnicity. And then finally we can define the action to take when multiple faces are detected in the livveness image. The the largest face will always be used for livveness scoring. So uh that's an option that we can set here. If we head into the ## Advanced settings and quality thresholds [06:56](https://www.youtube.com/watch?v=7-nJ3JE20i4\&t=416s) advanced tab, we have a few different options here. Here we've got the face privacy mode, maximum livveness attempt, so how many times a user can reattempt the livveness check within a single verification session, the face quality threshold. So, so if you are ever unsure of what these settings actually do, we can hover over this information button here. We can see face quality measures image clarity, resolution, sharpness. [07:20](https://www.youtube.com/watch?v=7-nJ3JE20i4\&t=440s) Low quality images may result from blur, pixelation, or poor lighting conditions. So we can set the threshold here based on the face quality score. We have a luminescence threshold. So we can set the acceptable luminescence range and then if the luminescence is below that range, we can obviously send them to review or decline. And finally, we can set up our own custom rules if none of these match the ## Return data and GDPR [07:47](https://www.youtube.com/watch?v=7-nJ3JE20i4\&t=467s) settings that we want. So in the return data tab we can select the data points that we would like to exclude from the verification results for GDPR etc. Now for each of these modules we can see the price of the check and then at the top ## How workflow pricing adds up [08:00](https://www.youtube.com/watch?v=7-nJ3JE20i4\&t=480s) here we could see a total price. So let me just sort of walk you through this because each node has its own price and each workflow is probably going to be slightly different in terms of the total cost. So you only pay for the steps that actually run. So each step is charged on its own. So if the applicant stops partway through the check, only those first few checks that they've gone through only going to be charged. So that's why you see at the bottom a range from 20 cents to 43 cents. That is the range. If somebody is going to go through the workflow, if they go through the first step and they exit, then it's only going to cost you 20 cents. If they fully complete the verification workflow, it's going to cost 43. And as you can see in the middle, these are all of the modules that are inside of this particular workflow. We can see how many credits we've got per month. Once those free credits are used up, once those 500 checks are done, then you will start getting build for them. So, one of the most powerful modules you can add isn't actually a camera check at all. It's ## Database validation against government registries [09:05](https://www.youtube.com/watch?v=7-nJ3JE20i4\&t=545s) database verification. So, let's just add this in. This is a background check. And we're going to take a look at what this actually does because this database validation check connects to official government registries and databases all over the world. So what it does is cross-check the users data against those official sources and then enrich it with extra fields the registry holds. So you can choose which registries and sources to run as you can see here for each country. And each service lists its own price. So you can see down here we've got different services inside of Canada for example and there's obviously different pricing for different registries. So if you wanted to see a specific country like Germany for example, we could see the checks that are available in Germany and we can select these based on our needs. [09:59](https://www.youtube.com/watch?v=7-nJ3JE20i4\&t=599s) And this database validation is not just something that you can run here in the dashboard is callable directly through the Didit API from your own backend too. And again, like with all of these modules, we've got rules, we've got advanced, and we've got return data. So again, you could set your rules here. And if we click here on partial match, we could see what a full match looks like. Full name and ID number, if that matches in the registry, for example, and a partial match maybe is just an ID number. And then we can decide what that partial match means inside of your workflow. Do we put it to review? Do we decline? Do we approve? So we have some branching inside of this workflow. We ## AML branching and conditional logic [10:36](https://www.youtube.com/watch?v=7-nJ3JE20i4\&t=636s) have AML branching depending on the AML risk score. AML is just anti-moneyaundering. But we can see down at the bottom we already have branching configured for this AML risk score. So we can see if the risk score is over 70, we can just decline and we can click into here. We can see the conditional logic. Right? So this is something that we can set up however we want. So we've got branch one, we've got branch two and then all other cases which means the session is going to be approved. So for example, if somebody is in this group here, they get sent to branch two. We could ask them for uh more information, right? We could ask them for proof of address, for example. So that way if somebody is a little bit risky, we can ask them for for more information that will help us decide whether this person should be approved or declined. So, one of the other nodes that we've got here is we've got status, and we've already been added here, but you can add those at the end of your workflow to determine what the outcome's going to be. So, another one of the ## The webhook node [11:40](https://www.youtube.com/watch?v=7-nJ3JE20i4\&t=700s) nodes that we can include in the workflow is the webhook node. So, the flow can also reach out to your own systems in the middle of a verification, and that's what this node is for. It can call an endpoint and pull data back. And so it's going to wait for that webhook to respond. You can see here we've got a post webhook. We've got a JSON payload which can be changed. Also, we can also send different payloads. So these are the key value pairs that maps your session fields into the request that you send out. And the fields that come back become variables for the next branch to test. So you're combining digits checks with your own risk data all inside a single flow. And one final thing we we can include the headers down here at the bottom. Some more key pairs. We got basic authentication here. All of the stuff that you would expect uh from a webhook call. Didit validates the ## Graph validation and errors [12:28](https://www.youtube.com/watch?v=7-nJ3JE20i4\&t=748s) graph the whole time you're building. So if a node is misconfigured or a path is broken, it's going to tell you exactly where. Right? So we click down here in the bottom. We see flow has two errors. And we can see branch one has incomplete rules. And it's going to tell you what needs fixing inside of your workflow. And we're not going to be able to publish this until these errors are fixed. So if I had a brand new workflow for example and there was an error then I wouldn't be able to publish that workflow. So beyond the individual nodes ## Workflow settings: retries, expiry, callback URL [12:58](https://www.youtube.com/watch?v=7-nJ3JE20i4\&t=778s) in the workflow we have the settings tab in the top here that we could see these settings apply to the whole workflow rather than a single check. We've got a workflow name of course we've got a call back URL which is the address Didit redirects the user to once the flow finishes. We can allow desktop access if you want to allow them to continue on desktop. We've got the retry attempts so you can change that. So, the amount of times a user can reattempt document capture within a single verification session. If a previous attempt fails, we've got the session expiration, so how long an unfinished session stays valid before it automatically expires. And this is going to apply to newly created sessions. And we've got the retry window, so the number of days within which retries are allowed. So from ## White-labelling the flow [13:43](https://www.youtube.com/watch?v=7-nJ3JE20i4\&t=823s) inside of this workflow, we can actually head over to the customizations tab by clicking this button up here. So white labeling is wired straight into the flow itself. So you can jump into this tab here and you could start tweaking how this verification flow looks, the colors, the branding, the email, the domain, all of that good stuff. And in the mockup here, you could see how it's going to look on mobile and also how it's going to look on desktop as well. [14:13](https://www.youtube.com/watch?v=7-nJ3JE20i4\&t=853s) You can also test it out in different languages. So if we put this into French, you could see every check is now written in the French language. And if you want to turn on, you know, you can switch on your branding here. Boom. You could turn it to what we set in the customization tab or we can turn that off. And we can actually see what happens if we choose a different path here and we can see what gets sent to the user. Now, obviously the user is not going to see the the pick a path module, but this is just to help us visualize what's going to happen on the next step, right? So, if they declined, we're going to see verification declined, verification in review, or that they've been verified. We do have the copy link ## The shareable link, and when not to use it [14:58](https://www.youtube.com/watch?v=7-nJ3JE20i4\&t=898s) at the top here. So, if we copy that, open a new tab, we can come through to the the link here, and we're going to be able to see what the user is going to see. And sometimes you just want to hand someone the flow without wiring any code at all. And this copy link does exactly that. It copies a ready to share hosted URL for this workflow. Now, this is handy for a quick test or a manual send, but it's not the recommended way to integrate this. For production, you can create a session per user through the SDK or the API carrying the vendor data and that's how you get real-time results back through webhooks and the SDK. So the copy link is great for tests and events and a proper session is what you're going to ship in production. So ## Version history and rollback [15:41](https://www.youtube.com/watch?v=7-nJ3JE20i4\&t=941s) at the top here we've got the version history. So we could see the different versions and we can restore or we can view the previous versions. And if we were to be editing this workflow, then those edits would sit as a draft um above the published history in here. And the cool thing is that every new version that you publish, it keeps the same workflow ID. So your backend keeps calling that one ID and it's going to get silently forwarded to the newest workflow that you've created cuz that history is tracked and you can iterate with confidence and roll back to previous versions whenever necessary. So for example, in this workflow here, this is a brand new one. You can see it's in draft mode. If we make any changes to the workflow, it's going to be in draft and we'll need to publish it. So, we can ## Publishing your workflow [16:24](https://www.youtube.com/watch?v=7-nJ3JE20i4\&t=984s) hit publish. This workflow is only going to go live when it's published. Uh, it's going to validate the graph to make sure there's no errors. And boom, we can grab the link and now this workflow is live and ready to go. Uh, let's take a look ## Integrating: SDK, API key and the setup prompt [16:37](https://www.youtube.com/watch?v=7-nJ3JE20i4\&t=997s) at the integration. So, there are multiple ways to integrate this. We can grab our target SDK. So whether we want React Native, iOS, React Next.js, we can select the workflow and in this case we got the high-risk country of review. We can select the API key. So we can have different API keys for different workflows or different integrations, whatever you want. Or you can select a webhook. So if you want to get notified of decisions, you can pop that into there. Now the easiest way to integrate this is we just copy a prompt and we can just slap that into claw code or codeex. [17:12](https://www.youtube.com/watch?v=7-nJ3JE20i4\&t=1032s) And that prompt is going to integrate this workflow. So even if you don't have didit integrated into your app yet, this prompt will give you everything that you need to have this workflow up and running into your app. Now you don't even need to do that. You could just ## Building workflows with the MCP server [17:27](https://www.youtube.com/watch?v=7-nJ3JE20i4\&t=1047s) install a Didit MCP server. Just describe the flow in plain language and it will create the workflow for you and automatically integrate it into your app. Tell it what to do and it will go ahead and do it. Now, we are going to get into how to set up the MCP in another video, but MCP is essentially model context protocol that allows you to build. with Didit using natural language in tools like Claude Code, Cursor, Codex, and all the rest. So, we can jump into customization real quick. [17:57](https://www.youtube.com/watch?v=7-nJ3JE20i4\&t=1077s) We'd add in the public name, privacy policy, URL. We've got the branding where we can change the colors. You can also pull your logos and colors automatically from your website, which could be super useful and easy to do. We can upload your logos down here. And you can see I've already set these colors. And to to test how it would look with those colors, if we just flick this switch here, we could see our white label branding getting implemented here on the verification flow. I'm just going to toggle it off for now. You can set a personalized email. You will need to fill out these details. And then when you continue to verification, you can just get the DNS information and hook that up with your domain. And the same here if you want to put a subdomain. So that this whole workflow is fully hosted using your own branding, your own domain. So this really is a seamless process for your users to go through the verification. # Integrate Didit: API, SDK and Webhooks Source: https://docs.didit.me/academy/integrate-api-sdk Video transcript: the developer integration path - session API, SDKs, webhooks, and going from sandbox to production. Full transcript of **Integrate Didit in Your App: API, SDK and Webhooks (Developer Guide)** - Didit Academy video 8 of 10, 08:13. [Watch on YouTube](https://www.youtube.com/watch?v=fX03-WEu_EI). Each paragraph links to the exact moment in the video. ## What you'll wire up [00:04](https://www.youtube.com/watch?v=fX03-WEu_EI\&t=4s) In this video, you'll get Dedit wired into your own app. So, your users verify right inside your product, and every result flows back to your system the moment it happens. This is the developers video, so it's a little bit more technical, but it's simpler than you think. And by the end, you'll see you can hand most of it straight to cloud code and have it build it for you. So, we'll go through it in order that ## SDK, API and webhook: the three pieces [00:28](https://www.youtube.com/watch?v=fX03-WEu_EI\&t=28s) you'd actually build it. Let's dive right in. Integrating Dedit means wiring up three things. The SDK renders the camera, the document capture, the NFC read, and the liveness UI right inside of your app. The API is server-to-server, so your back end creates the session and reads the authoritative decision. And the webhook calls your HTTPS endpoint the instant a session changes state, which is way ## The integrate tab [00:56](https://www.youtube.com/watch?v=fX03-WEu_EI\&t=56s) faster and richer than polling for it. So, the easiest way to integrate is to go to your manage tab, click on integrate, and we can just grab all the settings from in here, so we can grab our API key. So, we could set up a specific API key for this particular app that we're working on. We can create and choose a workflow that we want to integrate. We can add a webhook. So, this is where the verification results are pushed to. [01:24](https://www.youtube.com/watch?v=fX03-WEu_EI\&t=84s) And the signing secret, that I'll show you in a second, this is what's going to ## Choosing your platform [01:28](https://www.youtube.com/watch?v=fX03-WEu_EI\&t=88s) go in your ENV file. You can then connect it to your app. So, we've got a few different options here. We've got web JS, React Native, iOS, Android, Flutter, and a few other surfaces here. So, you can select the one that is relevant for your app. This is the environment secrets that you're going to put in your ENV file over on your ## The AI setup prompt [01:48](https://www.youtube.com/watch?v=fX03-WEu_EI\&t=108s) server. So, the easy way to set this up would be to use the AI setup prompt. So, we configure all the settings up here, and then we copy the prompt and it's going to copy all of the relevant information that we need from the setup that we've completed here. We copy and paste this, and we can pop that into Cloud Code or Codex or wherever you're ## API keys, one per environment [02:09](https://www.youtube.com/watch?v=fX03-WEu_EI\&t=129s) building your app. Your API keys live here, and each row has one key, okay? And so, a good habit is a separate key per environment per integration. So, you can rotate or revoke one without breaking the others. So, if you're going to integrate a specific workflow, you ## Creating a key [02:27](https://www.youtube.com/watch?v=fX03-WEu_EI\&t=147s) might want to just have a separate API key for that workflow, for example. Now, if I click create API key, um I'm just going to put test here, create the API key. Now, I can copy this, right? And I'm not going to see it again. So, it's important that you copy it and maybe note it down somewhere so that you can use it when you're doing the integration. When you come through to the integration section and you grab your API key, and let's say if I grab the test key and I come down, I select, okay, we want to use this uh let's see, KYC workflow. We can add a webhook. [03:05](https://www.youtube.com/watch?v=fX03-WEu_EI\&t=185s) We can connect our app, okay. And then we can pop in this setup prompt here. You can see here this prompt is going to ## Webhooks overview [03:13](https://www.youtube.com/watch?v=fX03-WEu_EI\&t=193s) include the API key. So, moving on to webhooks real quick, we can set up a webhook for basically anything that we want. So, say if you want to send a specific event to Slack, right? We can ## The documentation [03:25](https://www.youtube.com/watch?v=fX03-WEu_EI\&t=205s) add the webhook URL here. Okay, so let's take a look at some of the documentation here cuz you do have access to all the technical documentation. If you just go to docs.didit.me, and we're going to look at a few things ## Create session: the one required field [03:37](https://www.youtube.com/watch?v=fX03-WEu_EI\&t=217s) in here. Everything revolves around the create session. All right, so this is a post request. This is the start of a verification. So, we could see here in the curl request, we got the workflow ID. This is the only required field, and the really useful bit is that this same endpoint creates both KYC and KYB sessions. The ## Vendor data and callback URL [04:00](https://www.youtube.com/watch?v=fX03-WEu_EI\&t=240s) workflow is what decides which is which. So, we've got some additional fields down here, including the vendor data, which we've spoken about a lot in these videos. This is the unique identifier for each user, and you can define that as you wish, if it's an email or a unique identifier, and then we have the callback URL here. This is where the user is going to get sent after they've completed the verification workflow. So, ## Trying the endpoint live [04:24](https://www.youtube.com/watch?v=fX03-WEu_EI\&t=264s) if we scroll down here, we can actually try this out. So, if we click try it, we can actually create a verification session here. So, I'm just going to pop in one of the API keys here. Just going to create a brand new one, test two. I'll copy that. Pop this in here. We want to grab a workflow ID. So, pop over to here. We can grab this workflow ID here. Enter that into there. The vendor data is not required. Let's just do a a random string of numbers. [05:02](https://www.youtube.com/watch?v=fX03-WEu_EI\&t=302s) The callback, we can keep it the same here. None of this is required, by the way. I think this is because I have a test account here, but if you did want to test this endpoint, this is exactly how you would test it. Now, if you are a developer and you want specific answers here, you can check out the documentation. The MCP also has access to all of this documentation, so you can literally just integrate the MCP and ask Claude a question that you might have about something technical that's probably going to be in these documents ## Webhooks: why not polling [05:32](https://www.youtube.com/watch?v=fX03-WEu_EI\&t=332s) inside of here. So, let's talk about webhooks. We do have a tab here in the manage section for webhooks, and this is how your results actually reach you. Webhooks are the recommended channel because polling is pretty slow, and it's ## Adding a destination and picking events [05:44](https://www.youtube.com/watch?v=fX03-WEu_EI\&t=344s) going to cost you more requests, and it's going to skip events. So, we add a new destination in here. We can paste a URL. We can pick the events that we want. So, this is all the data that we want to send to this particular endpoint. And Diddy is going to hand you back a one-time signing secret, which I'll show you in a second. And the URL has to be directly reachable. So, no localhost and no private IPs. So, I'm just going to come out of here and we can scroll over to the right-hand side and we can we've got a few options here. [06:16](https://www.youtube.com/watch?v=fX03-WEu_EI\&t=376s) So, we can see here the number of events this webhook is listening to and we can ## The signing secret [06:19](https://www.youtube.com/watch?v=fX03-WEu_EI\&t=379s) copy the signing secret, which is going to be important for your integration. Now, when we do the setup the integration in the integrations tab, and I walked you through that we have a prompt, then the yeah, the signing secret is going to be in here for the webhook that you've selected in the setup. So, ## The webhook handler prompt [06:34](https://www.youtube.com/watch?v=fX03-WEu_EI\&t=394s) another one of the ways that you can leverage AI, we've got a pre-made prompt here that I found in the webhooks tab here. We could see if you want to set up our webhook handler with AI. We can check out the documentation and we can find an integration prompt here. So, this is going to cover identity verification, entity, and transaction. It's going to build it all out for you. So, it lays everything out. So, what to build, the signature headers of verification, the webhook event types that you just saw when we were setting up a webhook earlier. We've got the webhook envelope and a whole bunch more and we can also select where we want to paste it into, which tool that we're using here. [07:15](https://www.youtube.com/watch?v=fX03-WEu_EI\&t=435s) So, if you want to use this prompt, that's the easy way to get rolling with this and get your integrations set up. Everything I've just gone through in this video is accessible and queryable inside of your AI tool if you integrate the MCP server. So, you can just explain whatever you want to happen in plain English and Cloud Code will read the documentations and build the integration for you. So, you're just checking the work, making sure it's running and ## Recap [07:41](https://www.youtube.com/watch?v=fX03-WEu_EI\&t=461s) working rather than coding everything from scratch. So, that's Didit in your app. The SDK, your users see, the API that your back end calls, and the signed webhook that delivers the verdict that you build on. Trust the webhook, use vendor data everywhere, and lean on the setup prompt, so you're not hand-wiring the boring parts. You can head to didit.me, sign up for free, and you can have a verification run in minutes. # KYB Explained: Registry to UBO Source: https://docs.didit.me/academy/kyb-explained Video transcript: business verification end to end - registry data, documents, officers, ownership graphs, and UBO identification. Full transcript of **KYB Explained - Verify a Business From Registry to UBO, Start to Finish** - Didit Academy video 6 of 10, 11:05. [Watch on YouTube](https://www.youtube.com/watch?v=JEnW_sEe35Y). Each paragraph links to the exact moment in the video. ## What this video covers [00:03](https://www.youtube.com/watch?v=JEnW_sEe35Y\&t=3s) In this video, we're going to verify a business from start to finish. Checking a company is more than confirming a name. You've got to look it up in the official registries, work out who really owns it, screen the business and its owners, and collect the right documents. Didit pulls all of that into a single workflow called KYB. We're going to set it up, see what the company representative goes through, and then read the full result in the dashboard. [00:32](https://www.youtube.com/watch?v=JEnW_sEe35Y\&t=32s) So, let's get into it. All right. So, ## The business verifications dashboard [00:35](https://www.youtube.com/watch?v=JEnW_sEe35Y\&t=35s) let's navigate to the business verifications dashboard. So, this is KYB, know your business, and it verifies the company itself, its registry records, its owners, and you can see here, we're going to go into detail on one of these checks. This particular business is under review. And again, this is a demo account with demo data. But you could see the checks that this business has gone through, the checks that have been approved and the warnings right here. [01:03](https://www.youtube.com/watch?v=JEnW_sEe35Y\&t=63s) So, we're going to go through each of these tabs and I'm going to explain the details of each of these checks. Now, if ## Filtering for businesses in review [01:10](https://www.youtube.com/watch?v=JEnW_sEe35Y\&t=70s) you want to filter for all of the businesses that are under review, we can apply the filter in the status column. in review. You can see this particular business has been flagged on a lot of different fronts. Uh we can also check out some other ones here and we can see this business has been flagged on key people. So at the top just like with the user verification results we've got similar tabs and these tabs are related to the checks that this person goes through in a specific workflow. So up ## Warnings first [01:38](https://www.youtube.com/watch?v=JEnW_sEe35Y\&t=98s) top as usual the first place to look is the warnings. Where has this particular business been flagged? So you can see company officers data not available. So that's what we're going to be looking at when we're working through and figuring out if we can approve this business or not. Now we do have the business details ## Business details and vendor data [01:56](https://www.youtube.com/watch?v=JEnW_sEe35Y\&t=116s) here. The country, the session ID, and the vendor data ID. Now, we've gone through this in previous videos. The vendor data is what ties all of the checks and all of the transactions under one profile. We can take a look at the session ID when it was created, the vendor data again, and and the workflow. So the workflow this particular business has gone through. We've got a cost breakdown here of all the checks that have been applied to this business. And that's everything in the overviews tab. All right. So let me find another profile that's got more checks here so can walk you through in a little bit more detail. Again, this is a different company. Again, demo data. Got the cost breakdown, possible match found in the AML screening. So we're going to work through that. Let's take a look at ## The registry check [02:43](https://www.youtube.com/watch?v=JEnW_sEe35Y\&t=163s) the next tab. This is the registry check. This is going to happen with every business that you put through KYB. You can see the registry is active. Got the company name, the registration number, all of the information that we've pulled from the registry. So, there's a lot of stuff in here. I'm not going to walk you through every single field. It's going to be different for different countries, but just know there's a bunch of checks running on this particular registry check. In the background, you can see company country accepted, the ownership data is available, the company is active, and all of these other checks. And if you want a little bit more info on these, you can just hover over and see a further explanation. So, if you're responsible for coming in and reviewing these verifications, you can flick that to approve if you think that check is worth approving. So let's move on to the ## Key people: shareholders, officers and UBOs [03:34](https://www.youtube.com/watch?v=JEnW_sEe35Y\&t=214s) key people because a business is usually not just typically one person. There are many people involved and so we need to run checks on all of those people inside the business. All the shareholders, all the representatives that we can see here. There's plenty of people in this business that we're going to need to run checks on. So we've got a list, but we've al also got a hierarchy. We can see how that looks on this chart here. [03:56](https://www.youtube.com/watch?v=JEnW_sEe35Y\&t=236s) So keep it as a list. We're going to scroll down and again we've got a checks list. And if we hit this drop down, we can see there's only one check happening here on the key people. But if we scroll up, we can see fully verified, all parties clear. So we could flick that to approved. Now, if we keep going, we can ## AML screening and ongoing monitoring [04:12](https://www.youtube.com/watch?v=JEnW_sEe35Y\&t=252s) see the AML screening. So this is the same as the user verification, the KYC. And again, we've got a sanctions list that we're going to be matching against. We can flick on ongoing monitoring if we want to keep monitoring this particular user on an ongoing basis. Instead of just running the check once, we can run that on a weekly, monthly basis. You can see there is a match here, but the match status is inconclusive. We could see the the lists that this particular business has appeared on. If we click the drop down on the checks list, we can see no AML matches found. AML screening performed. So, there was a match found here, but it's it's not a particularly high risk. We can see that there is a ## KYB documents and signature integrity [04:50](https://www.youtube.com/watch?v=JEnW_sEe35Y\&t=290s) match found here, but again, inconclusive. We keep rolling with this. We got the KYB documents. We can see what's been verified, what's in review, and what's declined. The corporate documents that were submitted, and the information that was pulled from these documents. We can also see the document integrity. Was it signed by pen or was it digitally signed? And that's important to know, right? Because digital signatures are not as authentic as real signatures, right? We've got the checks list. Again, ## Device and IP analysis [05:18](https://www.youtube.com/watch?v=JEnW_sEe35Y\&t=318s) these are all the checks that are running on these documents. Like we saw in the KYC, we've got the device and IP analysis looking at where the IP is for the verification device and then where the actual proof of address location is based. Again, if we want to see the checks that are running on the device and IP analysis, we can take a look ## The event log [05:35](https://www.youtube.com/watch?v=JEnW_sEe35Y\&t=335s) here. And down here, we've got an event log. And this is probably going to be a little bit more busier than the KYC because there are going to be different people inside the business that are going to need to submit information. So, we're able to see here when files were uploaded, when the statuses have been changed, when the session was created, including the IP address of each of these actions, and finally, we've got ## Webhooks [05:58](https://www.youtube.com/watch?v=JEnW_sEe35Y\&t=358s) the webhooks at the bottom. So, when these webhooks were pinged, got all the ## Inside a KYB workflow [06:02](https://www.youtube.com/watch?v=JEnW_sEe35Y\&t=362s) information of these webhooks inside of this dropdown. So, what does an actual KYB workflow look like? So, let's just take a quick look inside the configure tab. We go into workflows and we can find a KYB workflow inside of here. Registry and documents. So let's take a look at what a basic KYB workflow looks like. We start off with a registry check. Check the key people. And let me just show you what appears over here on ## The ownership threshold [06:30](https://www.youtube.com/watch?v=JEnW_sEe35Y\&t=390s) the right hand side. So there's a bunch of settings here that we can tweak. So the ownership threshold. So set the ownership threshold used to exempt low ownership owners from verification. you know, if somebody owns 1% of the company, there's really no point in verifying that person. And we can set that threshold here by just using this slider. So, anybody who's below this particular value is exempt from identity verification. So, in the settings tab over on the right, we can set the ownership threshold on UBO ownership and shareholder ownership. We can change that so anyone below the ## Party verification and reusing KYC sessions [07:04](https://www.youtube.com/watch?v=JEnW_sEe35Y\&t=424s) threshold is exempt from identity verification. We can also select the party verification. You can select the ones in here. We can auto decline on UBO rejection. So if any UBO fails verification, we can just auto decline. Also, we want to wait for all of the UBO verifications before making a final decision. Uh we can turn that off if we want. We can reuse verified individuals. So we can reuse approved KYC sessions for the same person across KYB, which is pretty smart. And notify parties by email. We want to notify these people so we can get their verification for the KYB check. There is some more advanced settings here, but it's not the scope of this video. I just want to work through what else we've got here in this workflow. We've got the AML screening. [07:47](https://www.youtube.com/watch?v=JEnW_sEe35Y\&t=467s) So, very similar to KYC. We can set the risk threshold on here. Uh we've got the phone verification, email verification. Again, we've got a bunch of settings for each of these steps, but if you don't really know what to configure, you can just leave everything as default. And the cool thing is you can have a conversation with Claude to set all of this up for you and it can walk you through all of the settings and you can just tell it your preference and it will know which setting to change and tweak. [08:15](https://www.youtube.com/watch?v=JEnW_sEe35Y\&t=495s) So I'm not going to go through all of these individual settings. We will be here forever, but just know you can add additional steps in here. You can add branching based on the outcomes of specific steps in this workflow. Now, if ## What the company representative sees [08:29](https://www.youtube.com/watch?v=JEnW_sEe35Y\&t=509s) you want to see what this workflow actually looks like, we can head over to the customization tab by clicking this icon up here, and we can see what somebody would see on the other end when they're coming in to verify their business. So, we start off with the welcome screen. We find their company using their company name and their country. Then, they select their company because we've done a search on the registry. They're going to edit the company information, list all of the key people. So the UBOS's shareholders representatives phone number verification which they'll then enter in here email for email verification which they'll enter the code in here. And now they're not going to see this. This is the branching that I've put inside the workflow. But we're going to be able to see what that user sees on the other end if they go down branch one or the other branch. But I've not set that in this workflow. So we could you can see at the bottom I I just added this in just to show you as a demo. So we can delete that step. So that's exactly what someone's going to see on the other end. [09:30](https://www.youtube.com/watch?v=JEnW_sEe35Y\&t=570s) So if we want to check in on our data, ## KYB analytics [09:32](https://www.youtube.com/watch?v=JEnW_sEe35Y\&t=572s) we can go through to the homepage. We could check the analytics. We can add some tabs at the bottom here if you want. So we can come in here. We can check the business verifications. We could look at the the volume, IP locations, company locations, warning insights, conversion rate, conversion rate by country, um, automatic verdict breakdown, and we can add all of these to our dashboard. [09:57](https://www.youtube.com/watch?v=JEnW_sEe35Y\&t=597s) So, if you scroll down, you can see that we've added all of these business checks. Down here, we can see the Caribbe registry check, key people, AML screening. So, this is just a warning insights at a glance. So we can see our approved versus rejected, conversion rate from approved, decline, and in review. We can customize this. We can also run reports at the bottom and export any data that we want from that dashboard. So that's a business verified from start to finish. One workflow looked the company up in the official registries, screened the business and its owners against the watch lists and mapped out who really owns it with an identity check on each of them and pulled in the documents. And all of that comes back in the dashboard registry record and the company status, the ownership, the screening results and the documents with the same data available over the API. So if you want to run a KYB of your own, head over to didit.me. [10:54](https://www.youtube.com/watch?v=JEnW_sEe35Y\&t=654s) me. You can sign up for free and create your own business workflow today. # What Users See in a KYC Verification Source: https://docs.didit.me/academy/kyc-user-experience Video transcript: the end-user KYC flow step by step - branding, document capture, NFC, liveness, face match, and what happens on decline. Full transcript of **What Your Users Actually See in a KYC Verification (Full Walkthrough)** - Didit Academy video 2 of 10, 14:36. [Watch on YouTube](https://www.youtube.com/watch?v=LzGe-dMWjUw). Each paragraph links to the exact moment in the video. ## What this video covers [00:03](https://www.youtube.com/watch?v=LzGe-dMWjUw\&t=3s) When you send a customer off to verify with Didit, what do they actually see? Well, that's what this video is about. We're going to walk through the whole flow from their side. The exact screens a real person taps through after they click your link. a flow you fully brand in their own language on whatever device they've got with a stack of invisible checks doing the heavy lifting and the real result landing in your system the moment it's made and the best way to get a feel for it is to run one yourself. So head over to didit.me you can sign up for free and verify on your own phone in ## Opening the flow yourself [00:38](https://www.youtube.com/watch?v=LzGe-dMWjUw\&t=38s) a couple of minutes. Okay, so the easiest way for you to see exactly what your users go through is to open the flow yourself. So that's what we're going to do. Uh we're going to head over to one of our workflows here. We're going to copy the link and we're going to put it in the browser. So let's just take this basic KYC workflow. We're going to copy this link and we're going to pop it in here. So right here is the ## The first screen your user sees [00:58](https://www.youtube.com/watch?v=LzGe-dMWjUw\&t=58s) very first thing that your user sees after they tap one of your links. So the first thing to notice that well this is a demo for it. So we do have the Didit branding on here, but you can fully customize this. This list here is every step this particular user will go through. So we've got ID verification, face verification, and additional documents. So this list is not hardcoded. The workflow that this session is attached to is actually going to decide which steps show up and in what order. So this flow just renders ## Branding, and why it drives completion [01:28](https://www.youtube.com/watch?v=LzGe-dMWjUw\&t=88s) whatever is inside of that workflow when you turn it on. So the logo and the styling are yours, too. So to the user, this still feels like your product. That's pretty important because how much it feels like you and your brand is the single biggest lever on how many people actually finish this verification flow. So there is one small mark down here secured by Didit and even that's removable. Everything above is yours to configure. Did just the engine that's running underneath. So what your user sees is exactly the workflow that you set up wrapped in your brand. So here's ## The checks that never show a screen [02:00](https://www.youtube.com/watch?v=LzGe-dMWjUw\&t=120s) something that surprises most people. Not every check you see here has a screen. The only steps that show up are the ones that genuinely need the user to do something. So document, face, phone, email, and while they're working through those checks, a whole set of other checks is running server side with nobody touching anything. So device and IP intelligence, AML screening, ongoing AML monitoring, database validation, these are all happening in the background. The user never sees a step from any of them and you still get every result back in your dashboard. And that's how the flow stays super short while still doing a ton of work. Some of did its strongest checks at zero friction because they never face the user. So if you go back and look into one of these workflows, we could see here that we've got all these background checks. We got database validation. Uh we've got email verification, phone verification, AML screening, IP and risk analysis. So these are not public facing. These are all the checks that ## Customization: colours, logo, email, domain [03:00](https://www.youtube.com/watch?v=LzGe-dMWjUw\&t=180s) you can add into a workflow. So let's take a look at the customization tab. This is where you're going to be able to add in your branding, your colors, your own email address, your own domain, all of this stuff. As you can see here, we can change the name of the app. We can show the welcome page or turn it off. We could show the progress bar or turn it off. We've got the branding tab where we can add in all of these colors. Can add in the logo, the favicon, and change the typography. We can add a custom email. [03:25](https://www.youtube.com/watch?v=LzGe-dMWjUw\&t=205s) So, if you just pop in a name here, we can put in a an email address and we can continue to verification. This is going to give us the that's not worked out. But if we put in an actual working domain and we click continue to verification, that's going to give us the DNS records uh that we can add and we can set up a custom email address. And this email is where the notifications are going to get sent from and all the updates about the verification status. For the domain, we can also add a custom domain. So, we had a subdomain for example. And again, if you add in your subdomain here, it will give you the the records that you need to update on your domain provider. So you see this globe up here. The ## 54 languages, auto-detected [04:04](https://www.youtube.com/watch?v=LzGe-dMWjUw\&t=244s) interface ships in 54 different languages and that includes left to right scripts like Arabic. And by default, this flow just auto detects whatever language the browser is set to and falls back to English if it doesn't support that particular language. But the user can open this searchable list and switch into any language at any time and have every instruction follow their choice from there. And if you already know someone's language ahead of time, maybe on your own database, you can set this language when you create their session. So it opens in the right language without relying on the browser at all. So the flow meets the user in their own language automatically with 54 to choose from. So, if we take a look at ## Mobile vs desktop, and the QR handoff [04:49](https://www.youtube.com/watch?v=LzGe-dMWjUw\&t=289s) this preview, you see most people end up verifying on their phone. And that kind of makes sense, right? The camera makes capturing a document and a selfie super easy. Someone would just point their phone at this QR code and they'll be able to continue the verification process on their phone. When someone lands on this page on desktop, you could see here we can actually continue on desktop, but that's an option. You can force people to just verify through their mobile, but you can absolutely enable desktop and and let them finish right here on the computer instead. But if you do, just know that the livveness check gets forced to passive on desktop because the active version doesn't really play nicely with computer webcams. And what I mean by active versus passive is where you have to ## The hosted flow vs building your own screens [05:34](https://www.youtube.com/watch?v=LzGe-dMWjUw\&t=334s) blink on the camera. That's an active livveness check. Whereas passive is just a a photo. So the simplest path to get started is the hosted flow. You see when I hit this copy link and I open it up in my my browser. You could send the user a link and Didit handles all the hard parts for you. So the camera permissions, the document capture, the livveness, every fiddly device quirk. So you can drop this into your app through the SDK, an iframe, a redirect, or a pop-up. And if you'd rather build your own screens from scratch, you totally can. But then you're on the hook for all of that. We get into the integration side properly in another video, but for now just know that the link that you're sending that you're getting from this workflow is the hosted flow and it's tuned to get people through to the end. ## Detecting the issuing country [06:20](https://www.youtube.com/watch?v=LzGe-dMWjUw\&t=380s) Okay, so back into the flow. When the document step needs to know which country the ID is from, most of the time the flows already figured that out. It geoloccates the user from their IP the moment the page loads and pre-selects the issuing country. And here you can see that it's worked out. And if your workflow only allows one country anyway, that's just going to get selected automatically and they're never going to see this picker. Uh this example here is a KYC flow, but this is going to be exactly the same for KYB or any other workflow that you build. The engine just runs whatever steps that are configured inside of your workflow. So next, as you can see here on this preview, the user ## Choosing a document type [07:00](https://www.youtube.com/watch?v=LzGe-dMWjUw\&t=420s) is going to pick which government document they're going to show. So didit recognizes seven named types. There's passport, identity card, residence permit, driver's license, health insurance card, tax card, and social security card. But this list is filtered down to only the ones that are actually valid for the country we just detected. So the user can't pick something Didit can't read. And again, if your workflow only allows for a single document type, this whole screen gets skipped and they ## Capturing the document [07:26](https://www.youtube.com/watch?v=LzGe-dMWjUw\&t=446s) go straight to the capture page. So if we continue, we go to the capture page. So, as you can see here in this preview, I am on my desktop and so I can upload a file or I can take a photo. So, forcing a live capture instead. It's going to drive guided real-time photo with no uploads allowed. And that's your strongest setting against tampered or recycled images. So, on the upload side, the accepted formats are your classics, JPEGs, PGs, PDFs, and a few other file types, all under 10 megabytes. And if it's a PDF and it's password protected, it'll prompt for the password. So we can either upload or we can force a live capture and that's all configurable inside of your workflow settings. So as you can see here in this preview as they line up the document ondevice cues are checking the lighting and the sharpness and it captures automatically the moment the shot is good enough so the analysis can start right away. And it's not just reading the text off the card. Didit is running authenticity and tamper checks, a document livveness check that catches things like a photo of a screen or a printed copy. It's also doing security features and checking the MRZ validation across more than 130 document languages. [08:37](https://www.youtube.com/watch?v=LzGe-dMWjUw\&t=517s) And the thing that really sets this apart is it's all happening in real time. So the user finds out instantly if a document didn't work and you get the exact same data at the same moment. So everybody wins on speed. So for the ## The liveness selfie [08:50](https://www.youtube.com/watch?v=LzGe-dMWjUw\&t=530s) livveness check, they can take a selfie. The user just centers their face in the oval that will appear on the screen from this step that you can see here. And behind that simple screen, there's a livveness check proving a real present human is actually in front of the camera. And that's also what lets Didit match the face against the document they just submitted. So you could choose which livveness method runs here. And you can set it per workflow node, which we are going to get into in other ## Passive, 3D flash and 3D action [09:17](https://www.youtube.com/watch?v=LzGe-dMWjUw\&t=557s) videos. And there are three different settings. We've got passive where the user does nothing. We've got 3D flash where colored lights build a depth map and still asks the user to do nothing and a 3D action which adds the lights plus a randomized little action like blinking or turn the head. So it's one selfie step with three livveness strengths that you get to pick from. So ## The liveness video and scores [09:41](https://www.youtube.com/watch?v=LzGe-dMWjUw\&t=581s) let's take a look at what that livveness step gives you. It records a short video of the person and scores it. So, if we go over to the user verifications and maybe we scroll down and take a look at one of the users here, we can look into their profile. And don't worry, we're going to get into everything that's inside of this verification check in another video. But just to show you what the livveness check actually does and what it gives you inside of your profile is a short video that you can see here. [10:08](https://www.youtube.com/watch?v=LzGe-dMWjUw\&t=608s) So, we could play the video. And yes, this is just a video for demo purposes, but this is what will actually show up for each of your users in the verification step. We have a livveness score here in a percentage. I'm going to get into that in another video. So each of the methods, the passive or the active, spits out a livveness score from one to 100. And it runs presentation attack and deep fake detection on top. [10:30](https://www.youtube.com/watch?v=LzGe-dMWjUw\&t=630s) So the video gets saved right alongside the score. And you can come back and replay the video and read every score right here in the verification check. and also in the user's profile. So you walk away with the selfie video plus the livveness and the deep fake scores ## What happens when a step fails [10:45](https://www.youtube.com/watch?v=LzGe-dMWjUw\&t=645s) replayable whenever you need them. So what happens when a step fails? The user doesn't hit a dead end. They get a specific guided retry. And in the settings inside of your workflows, you can set the maximum number of retries, the retry window. Um but we're going to get into more of the settings and how these workflows work in another video. But when they do see a retry message, it's going to be precise. something like the document expired or retake this in a stronger light, not some vague generic error. So they know exactly what to fix and how many attempts that they get is configurable as I've just shown you here in the workflow. By default, the flow just lets them keep trying until they get through because the whole goal is to finish them, not to lock them out. So attempts are tunable and the default is ## The approved screen [11:30](https://www.youtube.com/watch?v=LzGe-dMWjUw\&t=690s) built so the user can always reach the end. So when every required check passes, the user lands here. So, a green check and a plain language. You've been verified. It tells them there's nothing more that they need to do and they can head back to your app. And here's the part that they don't see. Your app has already gotten the verdict in real time before they even tap away. So, approved is this green reassuring end screen and ## The under-review screen [11:54](https://www.youtube.com/watch?v=LzGe-dMWjUw\&t=714s) your back end already has the results. So, sometimes an automated check raises a warning rather than a clean pass or fail. When this happens, the user is going to end up seeing an orange clock instead of this green check mark. With the text underneath, your submission is under review. So on your side, the verification is going to come in to here under review. And it's going to be up to you, somebody on your team, to either pass them, to approve their application, to decline, to ask them to resubmit with more information. And the cool thing is that user is going to get an email the moment the status changes on their ## The declined screen [12:30](https://www.youtube.com/watch?v=LzGe-dMWjUw\&t=750s) verification request. So if a check genuinely fails, they're going to get a clear declined state. So they're going to get a red mark with the words, "We couldn't verify your information at this time," which explains the outcome without giving away any of your fraud logic. So what happens next is entirely up to your workflow. You can let them resubmit within whatever attempt budget that you set or route them into a support flow inside of your own app. So declined is a clear non-technical end ## Redirect vs webhook: which one to trust [12:58](https://www.youtube.com/watch?v=LzGe-dMWjUw\&t=778s) screen and you decide whether that means resubmit or support. So two things happen at the very end of this workflow and it's worth knowing which one to trust. Right? So first the user's browser bounces back to your app. So they land right back where they started but that part is really just a handoff for them. The thing you actually rely on is the result that your server gets at the same moment sent straight to your back end the instant the decision is made and that's the version that you build your logic on. Never what's just sitting in the browser. The nuts and bolts of wiring that up are a whole video on its own. And so we'll save that for later. But the takeaway here is simple. The user returns to your app and your system already has the real trusted ## Finding the session in your dashboard [13:41](https://www.youtube.com/watch?v=LzGe-dMWjUw\&t=821s) results waiting. Every verification is going to show up in the user verifications tab. We got the filters here. We could see approved, in review, approved, declined, and depending on the outcome of the verification and the workflow that they've gone through, then that status is going to update accordingly. Now, the ones that are in review are obviously the ones that you're going to need to pay most attention to. So, we can filter that out and just have all these in here for human review. And with each of these verification checks, we can click in and we can see every piece of evidence behind the results. And this value down here, the vendor data, this is the ID that your own system sent across when it created the session. It's your stable reference for that person. [14:25](https://www.youtube.com/watch?v=LzGe-dMWjUw\&t=865s) And Didit groups every session that shares the same vendor data ID under one profile? # Connect Didit to Claude With MCP Source: https://docs.didit.me/academy/mcp-claude Video transcript: connecting Didit's MCP server to Claude - running KYC checks, querying sessions, and editing fraud rules from chat. Full transcript of **Connect Didit to Claude With MCP - Run KYC and Fraud Rules by Chat** - Didit Academy video 4 of 10, 10:50. [Watch on YouTube](https://www.youtube.com/watch?v=I3UkFIhW548). Each paragraph links to the exact moment in the video. ## What you'll build [00:03](https://www.youtube.com/watch?v=I3UkFIhW548\&t=3s) In this video, you're going to connect Didit straight to Claude and then get real work done just by typing what you want in plain English. So, building a workflow, clearing your review queue, setting up fraud rules. All of it just from the chat. And the thing that makes this possible is the MCP, which lets an AI assistant securely use Didit's own tools. So, let's start with what this connection actually ## The hosted MCP server [00:31](https://www.youtube.com/watch?v=I3UkFIhW548\&t=31s) gives you and get it set up. So, Didit ships a hosted MCP server, so any MCP client can drive the whole platform. And so, the three products that you should already know by now map straight onto this one connector. So, there's nothing really new to learn about Didit itself. You just type what you want. Claude calls the matching tool and shows you the result. So, anytime it's about to change something, it'll ask you to confirm if you do have permission set inside of Claude. So, one connector turns Claude into a full Didit operator. So, we could see here at the top, we've just got a a link here that we can add straight into Claude. So, I'm going ## What the connector actually gives you [01:11](https://www.youtube.com/watch?v=I3UkFIhW548\&t=71s) to click that in just a second. But, what do you actually get with this MCP? Cuz this isn't just some wrapper around one endpoint. The connector exposes 108 different tools across 12 tool sets that covers sessions, workflows, KYB, fraud rules, cases, lists, webhooks. Basically, everything that you can do in this dashboard and all the data points, you can access through the MCP. And the cool thing is, you don't actually need to put in any API keys. You can just do an OAuth authentication one click. I'm ## Adding the connector in Claude [01:42](https://www.youtube.com/watch?v=I3UkFIhW548\&t=102s) going to show you and walk you through that in just a moment. So, let's add the Claude connector. So, we can add this in Claude desktop, right? We can add it in Claude code. We can set it up in CodeX. All sorts of different options for you there. All All so let's just click this link and add the connector straight into Claude, shall we? So we can add a custom connector. This is in the web version. [02:02](https://www.youtube.com/watch?v=I3UkFIhW548\&t=122s) We can add for now, and you can see it's added the MCP, but we're not connected to Didit yet. So we can click connect. You will sign in here. You'll log in. You'll authenticate. It'll redirect you back to Claude. And so when you come ## OAuth: authorizing without API keys [02:16](https://www.youtube.com/watch?v=I3UkFIhW548\&t=136s) through to authorize the application, this is the screen that you're going to see. And this is what permissions you're giving it. All right, so I'm just going to hit authorize, and you can see at the top connected to Didit. So I'm just going to see what we've got here. So you can see if we click that plus button, you can see connectors. I can see Didit is connected ## Listing the available tools [02:38](https://www.youtube.com/watch?v=I3UkFIhW548\&t=158s) here. So if I say "What tools do I have access to?" We'll be able to see the list of tools that we have access to here inside of Claude. So just like I mentioned earlier, we've got 121 tools that we've got access to in here. This is the list of everything. Now, don't worry if this seems like a lot. This is just all of the the data points that we can tap into inside of Didit. So yeah, from here in this chat, you can just describe what you want, and it's going to build it for you through the MCP. ## Claude Code, Codex and ChatGPT [03:12](https://www.youtube.com/watch?v=I3UkFIhW548\&t=192s) Now, if you are using a different tool like ChatGPT or Claude code, I mean Claude code is the same process. You'd have to just add the MCP URL, and then go through the authentication, signing with your account. It's going to be very similar for ChatGPT. I've got a few prompts here that I've I've developed, so I'm going to throw them in, and we'll see what we can create. Now, of course, you can create workflows. You can check your review ## Querying your review queue [03:39](https://www.youtube.com/watch?v=I3UkFIhW548\&t=219s) queue, all of this stuff. So So you can see we've got a permissions box show here. It's going to ask us to use this specific tool. Going to click always allow, or you can change to just allow once. I'm going to hit always allow. So, we can see the result set is pretty large. So, perhaps we could have filtered it and said, "How many verification sessions do I have in review in the last 7 days?" Now, because I am using a demo account here, nobody is actually going in and approving any of the verifications that are in review. [04:11](https://www.youtube.com/watch?v=I3UkFIhW548\&t=251s) So, the situation for you and your business, you'll have somebody doing that daily, depending on the volume that you're running. You're not going to have a huge backlog. So, you can see it's just pulling live data from our account, and let's get into an actual build. So, I'm going to pop this prompt in here, "Build ## Building a KYC workflow from one prompt [04:26](https://www.youtube.com/watch?v=I3UkFIhW548\&t=266s) me a KYC verification workflow." And then we're going to name the checks that we want. So, I want an ID document check that reads the document, extracts the data, passive liveness, face match, AML screening. Once it's built, set it as my default workflow. So, we do have another permission request that is going to ask you these permissions every time it's using a new tool. Boom, so we're done. [04:46](https://www.youtube.com/watch?v=I3UkFIhW548\&t=286s) That workflow is built. That was super quick. It was probably like 10, 20 seconds. So, let's go over to Didit and ## Checking the result in the console [04:54](https://www.youtube.com/watch?v=I3UkFIhW548\&t=294s) go into our workflows tab. Give it a refresh. And we can see KYC, liveness, AML, face match. And you can see last updated 1 minute ago. It's created as a graph workflow. ## Asking for a conversion-lift recommendation [05:12](https://www.youtube.com/watch?v=I3UkFIhW548\&t=312s) Boom. Pretty cool. So, what else can we build here? Well, I've got another prompt that I think would be really useful if you've been using Didit for some time and you already have some data. "Take a look at my current workflows and my recent conversion data, then suggest one specific change that would lift my pass rate without weakening fraud protection. Please show me the exact update before you apply anything." So, now again, I will say the account that I'm connected to is a demo account, so it doesn't have a ton of actual data, but we'll we'll see what it can come back with. That took a few minutes, but we do have some results back. We could see what's happening over the last 30 days. [05:52](https://www.youtube.com/watch?v=I3UkFIhW548\&t=352s) 443 sessions started, 84% conversion. But, look at the automated decision before human review. So, auto approved 338, auto routed to in review, so 24% of all sessions, and then 24 declined. So, we could see it's just done an analysis of the approvals and the verifications. So, we could see the mechanism your default workflow ends in a blanket determine. So, I'm not going to read through everything here. It has suggested one change, replace the default workflow as blanket auto decide with the same AML score bands. So, low score AML false positives get auto approved instead of clogging review. [06:31](https://www.youtube.com/watch?v=I3UkFIhW548\&t=391s) Kind of interesting. And you can run this analysis on your own account with your own data. And you can use AI to to help pull insights instead of having your team spend, you know, hours looking at your numbers and your reports. It's great just to pull reports straight from Claude. You can pull specific numbers. You can even create a nice formatted PDF report straight here from Claude that you can download, that you can present in your meetings. So, this is just a really cool way of accessing all of your data and then using AI to analyze it all in one place. You can see it's made a suggestion of what to change here. It's validated the analysis, and then we can go ahead and ask it to implement these updates. Like you see, if the publish live step is what gave you pause, you can apply it as an unpublished draft. [07:22](https://www.youtube.com/watch?v=I3UkFIhW548\&t=442s) Yeah. ## Applying the change as an unpublished draft [07:26](https://www.youtube.com/watch?v=I3UkFIhW548\&t=446s) So, we're going to apply it as a draft. So, if you did want to do this with a live workflow, and you wanted to check everything first before you change something that's live, then we can go ahead and do that, and you can see it's updated. So, we'll check that in a second. We'll just set this other ## Writing transaction monitoring rules [07:41](https://www.youtube.com/watch?v=I3UkFIhW548\&t=461s) prompt off. to set up two real-time transaction monitoring rules. So a velocity rule that flags too many transactions in a short window and a structuring rule that captures amounts kept just under reporting threshold. Back test both against the last 90 days of my history and show me what they'd have flagged before we turn them on. So this can be super useful if you want to develop new rules that might make your verification process smoother, faster, and easier. [08:09](https://www.youtube.com/watch?v=I3UkFIhW548\&t=489s) And then you can back test your data. So if we go over to didit, let's just take a look at the workflow that we had created. We can see the version history and we can see boom, we've got a draft here in the version history. Got the V2, we can publish that and boom, it's done that and you can see here at the bottom we do have the branching, which is the update that it was suggesting based off the AML screening. All right, so we've got a few questions here. Cord is asking ## Answering the clarifying questions [08:35](https://www.youtube.com/watch?v=I3UkFIhW548\&t=515s) us what the velocity rule should be. So how many transactions in what window? Let's do three in an hour. What reporting threshold and just under band? So we're going to flag Yeah, the 10K threshold. Let's do all apps, all categories. Boom. So it's just getting clarification on the specifics of the rules that we want to set up because I noticed that I didn't actually specify that. [09:00](https://www.youtube.com/watch?v=I3UkFIhW548\&t=540s) So it needs that information to create the rules and to run the back tests. ## Back-testing against 90 days of history [09:05](https://www.youtube.com/watch?v=I3UkFIhW548\&t=545s) So we can see it's completed the back test. It did take a few minutes to go through all of this data. You know, looking back, I should have specified a specific time period or a specific amount of records to back test on. You know, if you have tens or hundreds of thousands of transactions inside of your account, then that might be something to consider or using a model like Sonnet that would be much quicker. So we can see it's flagged a few users here where the transactions over three in one hour. And we've got the structuring multiple payments underneath that threshold. And you can see extrapolated to the full history, we've got a an analysis here. I'm not I'm not going to read through absolutely everything here, but you can see two things worth noting before you enable. [09:51](https://www.youtube.com/watch?v=I3UkFIhW548\&t=591s) It's given us some suggestions here. So, refine the rules, extend the back test. Uh we could even send a webhook to your Slack whenever these kinds of transactions come through or whenever somebody meets these specific rules. So, I'm just scratching the surface with what's possible here with these AI tools when you integrate with Didit. You can use it for analysis, intelligence, for flagging specific issues, for crunching ## Recap [10:15](https://www.youtube.com/watch?v=I3UkFIhW548\&t=615s) data, for building, for editing, the whole works. And that's the Didit MCP from end to end. One hosted connector, an OAuth login with no keys to paste, and 108 tools that let you build workflows, clear reviews, set up fraud rules, and figure out your declines, all just by asking. So, if you want to try it yourself, head over to didit.me, sign up for free, and add the connector just following the steps in this video. # Didit Academy Source: https://docs.didit.me/academy/overview Didit Academy video course with full transcripts: platform tour, KYC, KYB, workflows, transaction monitoring, integration and pricing. [Didit Academy: Identity Verification & Fraud Prevention](https://www.youtube.com/playlist?list=PLIikxNViJoCY) is the official video course on the [Didit YouTube channel](https://www.youtube.com/channel/UCDnTpf4XOflvmwVdMiPSRIA). Every video has a full, timestamped transcript here - each paragraph deep-links into the exact moment on YouTube. Video 1 of 10 - 10:59. Full transcript with timestamps. Video 2 of 10 - 14:36. Full transcript with timestamps. Video 3 of 10 - 18:54. Full transcript with timestamps. Video 4 of 10 - 10:50. Full transcript with timestamps. Video 5 of 10 - 14:26. Full transcript with timestamps. Video 6 of 10 - 11:05. Full transcript with timestamps. Video 7 of 10 - 13:05. Full transcript with timestamps. Video 8 of 10 - 08:13. Full transcript with timestamps. Video 9 of 10 - 06:37. Full transcript with timestamps. Video 10 of 10 - 09:08. Full transcript with timestamps. # Platform Tour: KYC, KYB & Transaction Monitoring Source: https://docs.didit.me/academy/platform-tour Video transcript: a full tour of the Didit console - dashboard, credits, KYC sessions, KYB, transaction monitoring, directory, API and MCP. Full transcript of **What Is Didit? Full Platform Tour - KYC, KYB & Transaction Monitoring** - Didit Academy video 1 of 10, 10:59. [Watch on YouTube](https://www.youtube.com/watch?v=skV9iUR2UhQ). Each paragraph links to the exact moment in the video. ## What this course covers [00:03](https://www.youtube.com/watch?v=skV9iUR2UhQ\&t=3s) Welcome to Didit. If you're just getting started, this is a quick tour of the whole platform. So, by the end, you'll know your way around and find anything on your own. That's the whole platform in one pass. Three products that follow your customer from the moment they sign up all the way through to ongoing monitoring, every check and every transaction rolling up into one profile, and you can work with all of it here in the dashboard, over on the API, or through an AI tool. If you want to jump in and try it, head to didit.me. You can sign up for free, and you can run your first verification in just a couple of minutes. Okay, so this is the first thing that you see when you log in. This ## The home dashboard [00:44](https://www.youtube.com/watch?v=skV9iUR2UhQ\&t=44s) is the home dashboard. This is where you're going to do everything in Didit. Build your verification flows, read your results, watch for fraud, handle your billing, and manage your team. So, over here on the left, this is the navigation rail, and that's basically the map of the whole platform. So, we're going to walk through this together. I'm going to take you through each of the tabs, so you know exactly where to go for each of the products and each of the settings inside of Didit. [01:10](https://www.youtube.com/watch?v=skV9iUR2UhQ\&t=70s) So, in the middle, that you can see here, this is a live overview of your traffic. So, on this side, where we see needs review, this is anything that's waiting on a human to make a decision. Over here, we've got recent activity, which is basically a live feed of everything happening across all of the ## Environments, credits and pay-per-success [01:26](https://www.youtube.com/watch?v=skV9iUR2UhQ\&t=86s) three products in real time. So, up here, you could see production environment, and this switcher lets you flip between your live app, your sandbox. You can obviously add another application here as well. And down here in the corner, this is where we've got the balance, so you can add your own credits, discounts if you add higher amounts into here. And Didit is pay per success, so you load up your credits and you only get charged when a check actually completes. [01:56](https://www.youtube.com/watch?v=skV9iUR2UhQ\&t=116s) So, that's the home base. We're going to get into all of these different menus and the analytics and the dashboard uh in this video and later videos, but this is where you're going to be spending most of your time. So, before we go any further, the simplest way to think about Didit it is really three products. They ## The three products, one customer lifecycle [02:12](https://www.youtube.com/watch?v=skV9iUR2UhQ\&t=132s) follow the life of your customer. So, first you authenticate, so you make sure that they're a real person. Then you verify them, so things like KYC, KYB, biometrics, and AML. Then you monitor them for fraud. Those are the three products we've got. User verification, so KYC. We've got business verification, KYB. And then we've got transaction monitoring, which watches the money flow. Just a quick note, the wallet and crypto screening aren't a separate product. They live inside the transaction monitoring, which we are going to get into in a lot more depth in other videos. [02:49](https://www.youtube.com/watch?v=skV9iUR2UhQ\&t=169s) So, we've got three products, one customer life cycle. So, let's dig into ## User Verification (KYC): sessions and checks [02:53](https://www.youtube.com/watch?v=skV9iUR2UhQ\&t=173s) the first product, shall we? User verification or KYC. So, we can just tap into this tab here. And you can see every verification that's been run on a person. Each one's called a session. So, a single KYC check can bundle a few different things together. Government ID check that actually reads the document in any language, not just basic text scanning. We've got the liveness selfie. We've got the face match between the two, the selfie and the ID. And plus got some background checks, proof of address, email verification, device and IP, all of this stuff. So, you could see here that the icons and these represent the checks that happen inside of this workflow that you could see tagged here. [03:36](https://www.youtube.com/watch?v=skV9iUR2UhQ\&t=216s) So, right now you could see we've got multiple statuses in this window. If we go back to the home page, we could see all of these need review. If we click view all and we go over back to the verifications tab, we can see that it's added the filter, right? So, if you want to add a filter for in review, we want to set a specific date range, we can do all of that in this dashboard. Whenever somebody gets tagged in review, this ## The review queue and webhooks [03:59](https://www.youtube.com/watch?v=skV9iUR2UhQ\&t=239s) means that the system can't auto decide. This means we need a human on your team, someone in the compliance, someone in your in your review team to actually come along and check out why this person was flagged for in review. And the second a decision is made, it's also pushed straight to your own back end by webhooks. So, your entire system knows instantly when someone has passed or is in review. So, we're going to get into reading a full result in another video, but the short version, KYC ## Business Verification (KYB) [04:27](https://www.youtube.com/watch?v=skV9iUR2UhQ\&t=267s) confirms a real person. So, let's get into KYB, so business verification. So, this one confirms a company instead of a person. It checks the business against official registries, it maps out who actually owns it, so the beneficial owners and the officers, and it can run an identity check on each of those owners all in one session. So, as you can see here, we've got the registry check, just like we saw in the user verifications, we've got these icons here that represent each of the checks that happen inside of a specific workflow. Don't worry, we're going to get onto workflows in a minute. [05:02](https://www.youtube.com/watch?v=skV9iUR2UhQ\&t=302s) So, you end up with the company's details, the key people getting verified, and all the supporting documents in one place. We're going to build a full KYB workflow end to end in another video, but for now, KYB verifies ## Transaction Monitoring (fiat and crypto) [05:14](https://www.youtube.com/watch?v=skV9iUR2UhQ\&t=314s) a company and the real people behind it. Let's take a look at the transaction monitoring tab here. This is the third product, and this is the fraud detection side of Didit. So, verifying someone at sign up only really covers them for the verification on day one. This part runs continuously after a user or business has onboarded and been verified. So, you could see here, we've got some payments declined, some approved, and again, we've got the filter section here at the top, and we can click this button, and it's going to automatically apply the filter to include all of the transactions that are in review. So, you send each payment over to Didit and a real-time rule engine scores it and opens a case if something looks off. So, it works for anything that moves money. [05:54](https://www.youtube.com/watch?v=skV9iUR2UhQ\&t=354s) So, fiat or crypto. And remember that wallet and crypto screening is built right in here. I'm not going to get into too much detail in this video. I'm just giving you an overview of each of these individual products. So, if you go back to the home page, you can notice the transaction flow in the same activity feed as your verifications. So, you can see here we've got transaction, we've got KYB, KYB. So, everything runs through in this recent activity panel here on your home page. Listen, there's a lot more under the hood here, but the point is simple. Didit watches money movement in real time right next to ## The Directory: one profile per person [06:27](https://www.youtube.com/watch?v=skV9iUR2UhQ\&t=387s) identity. Let's look at the directory tab at the top here. Let's go into users. So, this where everything ties together. We're going to look into the directory. We're going to check out the users. And everything we just looked at, the verifications and the transactions, all of it rolls up here into one profile per person. So, you can see here we've got a person here. You can see the checks that they've gone through. One session, we've got the country, and we have their user ID. So, each row is one individual. You've got the name, you've got the country, and Didit stacks up everything that person has ever done under this one single profile. You can see these little green icons here like you saw in the verifications and the KYB. These are all the checks that they've passed at a glance. So, you can see we've got ID verification, the liveness, the face match, the device and IP analysis. And this number here is every session stacked up under that one person. You can see just one session for this particular profile. You're also going to see the vendor data value. So, when we open up a profile, you also see a vendor data value. And that's the idea that your system sends across when it creates a session. So, in this case, it is an email address, but it can be a random number that's unique to this person. In this account, it's an email, but it can be any stable ID that your system uses. And below it is Didit's own internal ID for this profile. So, the vendor data is the key that ties everything together. So, every session that comes in with the same vendor data ## The business directory and linked fraud signals [07:48](https://www.youtube.com/watch?v=skV9iUR2UhQ\&t=468s) lands under this same person. Okay, so let's head over to the business directory. That's where your verified companies roll up in exactly the same way, one profile per company. So, every person in every business carries a single status, active, flagged if something needs a look at, like an AML hit, or blocked. Over in the business directory, when we click on a business, you're going to get their complete profile. So, we've got the overview, profile, the verifications, transactions, payment methods, documents, devices, location, cases, activity. Everything is here under this one business entity, because their verifications and their money all live under the same profile. So, a payment gets judged against who the person actually is. So, this is how Deduct can catch things that disconnected tools just can't, like the same device showing up across accounts, sudden spikes in activity, or whole networks of linked people. So, one profile gives you the full fraud picture. Let's go back to the home dashboard and check out some more of these tabs down here. So, down at the bottom of the rail, there are two ## Configure vs Manage [08:52](https://www.youtube.com/watch?v=skV9iUR2UhQ\&t=532s) sections where you set Deduct up. So, we've got the configure tab here, and we've got the manage tab. So, configure is everything that your users will see and experience. So, that's workflows, so where you build your verification flows, customization for your branding, questionnaires for any custom questions, and lists for your allow and block lists. And don't worry, we're going to get into these in other videos. But, just a little preview here in the customizations tab, you can actually see how this verification flow looks and how you can customize it. So, the second panel here on the left is manage, and this is how Deduct connects to your own app. So, that's where you integrate it, you grab your API keys, you set up your webhooks. So, results get pushed to you, and it's also where you handle your team and pull your reports. We're going to spend whole videos inside both of these tabs later on, but for now, configure builds the experience and manage connects it to your product. So, the ## Building your own dashboard [09:46](https://www.youtube.com/watch?v=skV9iUR2UhQ\&t=586s) last thing I want to talk about here is back on the home page, we can actually build our own dashboard. So, the cool thing here is we can actually add cards however we want. So, these widgets, demographics, conversion rate, the locations, we can add them, we can drag and drop, we can move them around. We've got these filters here, we can filter by different date ranges. We can also look at the performance of specific workflows, and we can see all of that in this customizable dashboard below. So, the last thing to note is that everything that I've just walked you through, so creating sessions, building workflows, reading results, changing a ## Doing all of it over the API and MCP [10:18](https://www.youtube.com/watch?v=skV9iUR2UhQ\&t=618s) status, all of that you can also do in code. So, you can grab an API key under the manage tab here on the left, and the whole platform is yours over a simple API. So, you can build your own dashboards, you can automate anything without ever logging in to this dashboard. You do all of that inside of Codex or Claude Code, also with the MCP server. So, we're going to get into that in another video, but that is the dashboard at a glance. And there's another way to work with Didit on top of that. It has an MCP server with over 100 tools, which lets AI assistants like Claude, Cursor, and Codex work with it directly. So, you can use Didit right here in the dashboard, in your own code, or straight from an AI tool. # Didit Pricing Explained (Video) Source: https://docs.didit.me/academy/pricing Video transcript: how Didit pricing works - pay per successful check, 500 free checks a month, per-feature prices, no contracts or minimums. Full transcript of **How Much Does Didit Cost? Pricing Explained (500 Free Checks a Month)** - Didit Academy video 10 of 10, 09:08. [Watch on YouTube](https://www.youtube.com/watch?v=aTWy1rfChhI). Each paragraph links to the exact moment in the video. ## Why Didit publishes its pricing [00:04](https://www.youtube.com/watch?v=aTWy1rfChhI\&t=4s) Let's talk about what Didit actually costs. Most verification vendors hide their pricing behind a sales call, but Didit puts everything out into the open so you can work out your own costs ## The pricing page [00:16](https://www.youtube.com/watch?v=aTWy1rfChhI\&t=16s) before you ever sign up. So, let's head over to the pricing page and break it all down. Okay, so let's start right here on the pricing page. And notice I didn't have to log in to see any of this pricing. Didit publishes every price openly, which most vendors simply won't do. The model is simple. You start free and you pay per successful check for only the modules that you turn on. And you can scale all the way to enterprise on the same account. And every module's price is listed here with no minimums and no contracts to begin. And you're charged only for the checks that you actually run. So you can compare the ## The three plans [00:52](https://www.youtube.com/watch?v=aTWy1rfChhI\&t=52s) cost of each check before you ever sign up. So as you can see here there's three plans and the thing to understand is that you pick by volume and the terms that you need not by features because the same modules are available on every plan. So there's three tiers. There's free, there's usage based and there is enterprise. Free gives you 500 verifications every month plus blocklist and duplicate detection checks on every session. Usagebased is payer use across dozens of modules with no monthly minimum fee. An enterprise adds a custom master service agreement, an SLA for large volumes and regulated programs. So you're choosing by volume and terms and the same checks. They're on all three. ## What the free plan really includes [01:38](https://www.youtube.com/watch?v=aTWy1rfChhI\&t=98s) Now, if we take a look at the free plan, this is a real production tier. This is not a sandbox. It cost \$0 a month and needs no credit card. And several anti-fraud checks are already included on every session at no cost. So, every session is screened against your block lists for free. Duplicate detection captures the same person signing up ## 500 free credits, every month [02:01](https://www.youtube.com/watch?v=aTWy1rfChhI\&t=121s) twice, which is matched on the vendor data ID that you send over. And over 200 device and IP fraud signals get analyzed on every session, again, at no cost. So, it's a free tier that you can genuinely run in production. You get 500 free verification credits every month, and I'm going to show you the features that you can do that on in just a second. So, if we go into Didit and we check out the workflows and let's say if we So, let's say we open up a new workflow, we do user verification, uh we do simple workflow, start from scratch, you're going to see the pricing of each of the modules. So you can see ID verification ## The usage-based plan [02:41](https://www.youtube.com/watch?v=aTWy1rfChhI\&t=161s) 500 free per month, livveness 500 free and face match 500 free. And also I mentioned earlier the device and IP analysis again you get 500 free verifications. So the allowance resets on the first of each month. And while unused checks don't roll over, you always get a fresh 500 and it's permanent, not a timelimited trial. So that's 500 free identity checks a month forever. Now, if we take a look at the usagebased plan here in the middle. So, when you outgrow your free tier, you move to usagebased, the pay-per-use plan. It's the same account, no migration. You just start paying for what you run beyond the free allowance. [03:21](https://www.youtube.com/watch?v=aTWy1rfChhI\&t=201s) It's essentially pay as you go across dozens of modules. So, again, if we go back into the workflow, we could see what modules that we're going to need to pay for straight out the gate and which modules we're going to have to pay for after we've used up our 500 free credits. So you can turn whatever modules on or off that you want to use in your verification flows and you'll only pay for the successful checks that a user goes through. So that's why we see at the top here we've got a price from \$0 to 15. And if we click on the ## How a workflow's price is assembled [03:52](https://www.youtube.com/watch?v=aTWy1rfChhI\&t=232s) pricing, we can see how this workflow is priced. So you see you only pay for the steps that actually run. So if somebody enters the workflow and leaves immediately or after that first check, you're not going to pay anything because the first check is ID verification which is free. You're not going to pay anything because the ID verification you get 500 free. Okay? And after that it's ## KYB pricing [04:15](https://www.youtube.com/watch?v=aTWy1rfChhI\&t=255s) only going to be 15 cents. So that's going to be the maximum cost of this workflow. And it's the same for KYB. So the business verification. So, if we go into a KYB workflow, we can take a look at some of the modules inside of there. If we zoom in here, we could see the registry check \$2. The KYB is variable because it's going to depend on how many people we need to verify on that step. [04:39](https://www.youtube.com/watch?v=aTWy1rfChhI\&t=279s) Got the AML screening. If we want to add in any additional checks, we can do that here. And just know this AML screening is 20 cents per check, but that runs people against over 10,000 data sets covering sanctions, PEPS, adverse media. ## Database validation pricing [04:55](https://www.youtube.com/watch?v=aTWy1rfChhI\&t=295s) So the only other module that is variable on cost is the database validation. So if we add that node into here, we click database validation and you see the panel that opens up here on the right. You can see we can select whichever database validation we want to run. And this is country specific and database specific. You can see if we want to run a credit check, it's going to cost us more than checking the consumer data, for example. But the cool thing is you can see the cost of absolutely every check in here. So you're not going to be surprised when somebody runs through this workflow and you're you're wondering why is this costing so much? The price is going to appear up at the top here. And you can see it is variable. It just depends on how far somebody gets through this step. [05:40](https://www.youtube.com/watch?v=aTWy1rfChhI\&t=340s) So if I select a database in here, you can see it's going to give us a a price ## White-label pricing [05:44](https://www.youtube.com/watch?v=aTWy1rfChhI\&t=344s) down here. So the only other thing that I haven't mentioned here is the white labeling. So if you want to set up the white labeling, we can turn that on. It's going to cost 20 cents per verification. And you can see when we toggle this on, the price at the top, it's going to change. So this is going to consider the ## No minimums, no contracts [06:03](https://www.youtube.com/watch?v=aTWy1rfChhI\&t=363s) cost of absolutely everything inside of this workflow. You can see custom branding extra 20 cents. So with Didit there are no minimums. There's no contract on the self-s served plans and there's nothing to commit upfront. So if you spend nothing in a quiet month your account stays open and with the free 500 a month still available. So if you spend nothing in a quiet month your account stays open with the free 500 a month credits still available. Uh the usage plan has no monthly floor, no platform fee, no seat fee. So your bill is ## Why the prices are this low [06:34](https://www.youtube.com/watch?v=aTWy1rfChhI\&t=394s) exactly your usage and nothing more. You might be wondering how the prices come in this low. You see, Didit runs its own optimized verification infrastructure with sub 2C inference? And that's why a complete identity check from about 30 cents is typically 70 to 80% cheaper than comparable providers for the same checks. And because it's all published openly, you can compare line by line instead of negotiating a ## Enterprise [07:01](https://www.youtube.com/watch?v=aTWy1rfChhI\&t=421s) hidden quote. So for large volumes and regulated programs, there's enterprise. It gives you custom pricing with volume discounts on top of the public per module rates. You also get access to a dedicated Slack channel, the WhatsApp channels with manual reviewers on demand and reseller and white label terms with four deployed engineers who build alongside you. at high volume, the team genuinely recommends it because they like working closely with customers to fit into their flows and improve their KPIs. So, if you're running serious volume here, that's the conversation to have. So, let's head over to the billing ## Billing, top-ups and auto-recharge [07:40](https://www.youtube.com/watch?v=aTWy1rfChhI\&t=460s) section inside of our dashboard here. The bottom here, we have our current balance. This is where you're going to get build from. So, you're going to need a prepaid balance to use Didit. Now, as you can see here, there are discounts depending on how much you decide to top up. You can also set the auto recharge function as well, so you can keep running your checks without your balance going to zero. So, if we head over to the settings tab here, we can head over to billing. And again, we've got options to top up. We've got previous deposit history in here as well. And the amount that you top up in here, your credits, they never expire. So, if you need your invoices for your accounting team, you can just come in here and download them. ## The usage tab [08:18](https://www.youtube.com/watch?v=aTWy1rfChhI\&t=498s) So if we head over to the usage tab, this is where you're going to see exactly where your credits go. So you can see the spend breakdown module by module and you can filter by date range at the top here and by application. So if you have multiple applications, you can see which application is spending on which checks. So the whole thing is ## Recap [08:38](https://www.youtube.com/watch?v=aTWy1rfChhI\&t=518s) refreshingly simple. You start free every month and you only pay for the checks that you actually use. And the credits that you buy, they don't expire. So, there's no contracts, no hidden fees, and you can see every price for yourself before you commit a penny. Honestly, the best way to know your real number is to just start using it. So, head over to diddit.mme, sign up for free, and run your first verification in a couple of minutes today. # Real-Time Transaction Monitoring Rules Source: https://docs.didit.me/academy/transaction-monitoring Video transcript: setting up real-time transaction monitoring - fraud rules for fiat and crypto, alerts, cases, and wallet screening. Full transcript of **Real-Time Transaction Monitoring: Fraud Rules for Fiat and Crypto** - Didit Academy video 7 of 10, 13:05. [Watch on YouTube](https://www.youtube.com/watch?v=Yhm63_n7HuU). Each paragraph links to the exact moment in the video. ## What this video covers [00:04](https://www.youtube.com/watch?v=Yhm63_n7HuU\&t=4s) In this video, you'll see how Didit watches the money moving through your app and catches the transactions that should worry you. Checking who someone is when they sign up is one thing, but it doesn't tell you what they'll do once they start moving money around. That's the job of transaction monitoring. It scores every payment the moment it lands, ties it back to the person who made it, and flags the things that actually matter. So, a sudden spike in activity, a payment that's far too big, or a match against a sanction list. It works for regular money and for crypto, all against rules that you set yourself. [00:40](https://www.youtube.com/watch?v=Yhm63_n7HuU\&t=40s) So, let's open it up and walk through it. All right, so we can head over to the ## The live transaction feed [00:45](https://www.youtube.com/watch?v=Yhm63_n7HuU\&t=45s) transactions tab here on the left. And this is a live feed of every payment Didit is watching. So, it's ranked by date, so the newest first, and each row is one economic event. So, we're talking a deposit, a withdrawal, a transfer, a payment, a payout, or a bet. And every one of them gets scored and decisioned in real time as it arrives. So, the place that you'll probably want ## The review queue and filters [01:12](https://www.youtube.com/watch?v=Yhm63_n7HuU\&t=72s) to head to first is this tab here, 100 transactions to be reviewed. We'll click on that, and it's going to automatically filter out the transactions that need to be reviewed by your team. And if you want to see everything, we can add the filter all statuses. We can refine this if we want, if we want to select a specific day in the last 7 days, for example. If you want to search for a specific transaction ID or a Didit ID. If we want to look in specific currencies, etc. [01:42](https://www.youtube.com/watch?v=Yhm63_n7HuU\&t=102s) But for today, we're just going to flip the status to in review, and these are the ones we're going to walk through because these are going to be most important for you and for your own use cases. So, we ## Every transaction tied to an identity [01:52](https://www.youtube.com/watch?v=Yhm63_n7HuU\&t=112s) can see this transaction here is connected to a specific identity because nobody in your platform is going to be able to complete transactions without going through the KYC or KYB. We can see the type. This is crypto in this scenario. The amount, any tags that are involved, and the date that it was created. Now, one thing to note here is that we actually have the counterparty ## Counterparty screening [02:15](https://www.youtube.com/watch?v=Yhm63_n7HuU\&t=135s) here. They also get screened against sanctions and watch lists. The same AML engine that your identity checks already use. You can see we've got the score here. I'm going to jump into the transaction. I'm going to show you exactly what's going on here. So, if we click on one of these, again, I will preface this by saying this is this is demo data. This is not a real transaction, but to show you how this works, I want to walk you through each of these tabs. So, if we scroll down, each of these tabs corresponds to a tab up top here. Just like in the KYC and KYB, we can change the status here, download as a PDF, we can add to a block ## The overview tab and risk score [02:49](https://www.youtube.com/watch?v=Yhm63_n7HuU\&t=169s) list. So, let's take a look, right? So, in the overview section, we've got the risk score. So, this is medium. Uh it's been flagged as in review. We can see all of the warnings here. So, in the crypto monitoring, cuz this is a crypto ## Wallet risk and what the score bands mean [03:01](https://www.youtube.com/watch?v=Yhm63_n7HuU\&t=181s) transaction, we see there's a high wallet risk score. And we can read what this actually means. So, if the risk score sits between 70 and 89, it's going to escalate it for review. So, wallets at this score have a meaningful exposure to illicit clusters, like mixers, darknet markets, and scams. So, these are all the things that we want to be looking out for when we're reviewing this particular transaction. We could see it's been flagged for a large single ## Vendor data [03:28](https://www.youtube.com/watch?v=Yhm63_n7HuU\&t=208s) transaction. Now, just like with the KYC and KYB, we've got the vendor data here. So, all of these transactions for this particular vendor data, so in this case we're using an email, and it can be a unique identifier. So, this person will have gone through KYC. And all of the transactions that correspond to this vendor data will be ## How the risk score is calculated [03:52](https://www.youtube.com/watch?v=Yhm63_n7HuU\&t=232s) flagged underneath this particular user. So, you might be thinking, well, where does this score come from? You could see the risk score is 284, there's three rules matched, eight rules evaluated, and one open alert. Like, what's going on here? Well, every transaction is decisioned the moment it arrives, and each rule that matches adds to a cumulative risk score. And so, your thresholds decide when that ## The four transaction statuses [04:17](https://www.youtube.com/watch?v=Yhm63_n7HuU\&t=257s) score is high enough to send it to review or to decline it outright. So, in transactions, there are actually four statuses. We've got approved, meaning the transaction is clean, in review, like this particular example here, we've got declined, and then we also have awaiting user. So, when a rule needs a bit more assurance before it lets a payment through, the status flips to awaiting user. So, Didit quietly spins up a linked verification session, hands back a URL, and the user re-verifies themselves, and the transaction picks up where it left off. ## Getting transactions into Didit [04:51](https://www.youtube.com/watch?v=Yhm63_n7HuU\&t=291s) So, before we start digging through all of this information here, how do we actually get transactions into Didit? Well, we can import them from a CSV or a list. We can integrate, which is going to be the obvious option for for most of you watching this. You integrate with the SDK. And we can also create a manual transaction, and this really is only going to be for testing purposes. [05:15](https://www.youtube.com/watch?v=Yhm63_n7HuU\&t=315s) It's going to be a massive hassle to create a manual transaction every time a transaction runs through your company. So, if you click integrate, you can see we can just literally copy the prompt, select an API key, and then we can paste that into our cloud code or code X, and it will automatically set up the installation, so that your transaction monitoring is completely set up. Okay, so let's work through some of these checks and tabs here, and let me explain what each of them mean. Now, there is a lot of information in in but the reason why this account was flagged is because of the rules, and we'll get into the rules ## Transaction details [05:49](https://www.youtube.com/watch?v=Yhm63_n7HuU\&t=349s) section uh a little bit later on. But, we can see here this this is all of the transaction details that we've got here, crypto outbound, uh the country from Argentina to Netherlands, the transaction ID, the payment ID, payment details, and the vendor data, and the the currency amount. We've got the AML risk score. This just means the score that we get from the anti-money laundering module. [06:13](https://www.youtube.com/watch?v=Yhm63_n7HuU\&t=373s) We can look at all of the specifics of the transaction, the chain, the wallet risk, in this case potential scam wallet risk, the beneficiary wallet, and the wallet score risk. We've got some alerts here, the simulated crypto exposure. This is demo crypto transaction flagged by synthetic monitoring metadata, and ## The crypto exposure visualization [06:30](https://www.youtube.com/watch?v=Yhm63_n7HuU\&t=390s) medium. We've got the crypto monitoring. This is really cool. Let's click visualization, and you're going to be able to see the visualization of the wallets, how they're connected, the transactions. So, this can be really useful if you're trying to spot scams, and mixers, things like this. So, we've got the whole transaction overview here. You can see we've got an analysis here from Merkle Science. This is a third-party tool that you can integrate here into Didit for crypto screening and transaction analysis. If we keep going down here, this is all part of the crypto ## Counterparties [07:03](https://www.youtube.com/watch?v=Yhm63_n7HuU\&t=423s) monitoring from Merkle Science, transaction summary, exposure table, and then we get to the counterparties. So, this is the person who is receiving the the funds in this particular transaction. We can see this person is not verified inside of the current system, so it's going to check if this particular wallet is already inside your platform, and then this is the important part down here at the bottom. These are ## Triggered rules [07:27](https://www.youtube.com/watch?v=Yhm63_n7HuU\&t=447s) the triggered rules. So, we're going to look at these rules in a moment and see how we can set these up for our transaction monitoring, but if you click on each one of these, you could see what each rule is all about. So, we've got the rule identity, the trigger, the conditions, the actions, deploy settings. I'm going to run you through these in just a moment. You see there's related transactions down here. [07:48](https://www.youtube.com/watch?v=Yhm63_n7HuU\&t=468s) Yeah, it's a lot of information, but the the thing to focus on is the rules. So, let's go ahead and create some rules, ## Creating a rule [07:55](https://www.youtube.com/watch?v=Yhm63_n7HuU\&t=475s) shall we? Now, there is a library of rules. These are defaults that you can set up when you start a brand new account. We've got the installed rules that you can set up manually. We can create the rules here, so rules are essentially filters. So, if this happens, then do this. That's essentially what a rule is doing. So, we can give it a name. We'll call it test. We can add a description if we want. We can add a specific category. ## Triggers [08:18](https://www.youtube.com/watch?v=Yhm63_n7HuU\&t=498s) So, let's say we select geography and we move over to the trigger. Triggers on all transactions. We could specify by the channel, so crypto or fiat. Let's do crypto. ## Conditions [08:29](https://www.youtube.com/watch?v=Yhm63_n7HuU\&t=509s) The entity type, we can specify by individual or company. I'm going to do individual. We go through to the conditions. We can look for, I don't know, travel rule. Uh we can look for subjects. We can look for the country equals maybe if we put a high-risk country on there, somewhere in Africa, for example. We can add an additional condition here as well. So, if someone's putting multiple transactions through in a short space of time from this country, then that's what this rule is going to flag. And then we ## Actions and scoring [09:01](https://www.youtube.com/watch?v=Yhm63_n7HuU\&t=541s) can decide whether that's going to decline the transaction or put them into review. So, you can see here, choose what happens on a match. We change the status, right? We could add points. Okay, so that's what I was mentioning earlier. That's how the score is calculated. So, we can say add maybe 50 points in here, for example. And then ## Back-testing and deploy settings [09:24](https://www.youtube.com/watch?v=Yhm63_n7HuU\&t=564s) we've got the deploy settings. We can back test the rule to see how many hits this rule is going to get. Now, this is important because if you have a very restrictive rule, that's going to mean a lot more work for your team. So, you've got to evaluate the the risk versus reward of setting up these kinds of rules and how strict you want to be with this. Now, you can see on here, each rule shows you how often it fired and how much of that was sent to review or declined. For example, you got this percentage just here, and this is the data that you're going to lean on to tune the rule. So, if setting up your own rules seems like a lot of work, you could just actually have a conversation with Claude and say, "We want to filter out these kinds of people or these kinds of transactions. ## The rule library [10:07](https://www.youtube.com/watch?v=Yhm63_n7HuU\&t=607s) We want to detect this kind of behavior from these countries." You can also look in the library and we've got different categories here. We've got AML, nominee detection, crypto monitoring, device intelligence, finance for protection, responsible gaming, travel rules, and so there's a library of different rules that you can pull from inside of there. So, there's one condition in this rule ## Velocity conditions [10:33](https://www.youtube.com/watch?v=Yhm63_n7HuU\&t=633s) that I was working on earlier is the velocity condition. And this is pretty clever. So, instead of judging one payment in isolation, a rule can add up or average activity over a specific window of time. So, anywhere from an hour to 90 days, grouped by the user, the device, the IP, the payment method, or the counterparty. So, that's how you're going to catch structuring and sudden bursts that no single transaction would ever reveal. [10:59](https://www.youtube.com/watch?v=Yhm63_n7HuU\&t=659s) So, we could hit velocity condition. So, we can do the count of transactions in the last 24 hours for the same user, and we can specify is greater than, let's say, five, for example. So, that's the velocity condition. I think that's pretty clever. I've not seen this in any other platform. The idea being that AI can surface hidden patterns from your own history. Now, you could do this with Claude right now. You could hook up the MCP, ask Claude to analyze your data, and create rules ## Turning on crypto monitoring [11:26](https://www.youtube.com/watch?v=Yhm63_n7HuU\&t=686s) based on the patterns that it's seeing. So, if you were wondering where to turn on crypto compliance and the crypto monitoring integration. You can see here in the transactions tab, we can go to settings. We can adjust the risk threshold and then we can select the crypto monitoring Merkle Science. We can turn that on 15 cents per check. You can bring your own key, that's going to be happening sometime soon in the future. So, we can flip that on or off to your own needs. [11:54](https://www.youtube.com/watch?v=Yhm63_n7HuU\&t=714s) So, one final thing on the dashboard, ## Transaction analytics [11:56](https://www.youtube.com/watch?v=Yhm63_n7HuU\&t=716s) again, we can adjust our analytics here to include transaction monitoring as well. So, if you click on add, we can come through to transactions. We can take a look at the volume, for example, the action breakdown, approved versus rejected, and then we can add that to our analytics dashboard. And you can see that's going to appear down at the bottom here. And to move these tabs around, we just click edit, and we can let say we remove this one, and yeah, we can move these around like this. We can change whatever order we want them in. ## Recap [12:34](https://www.youtube.com/watch?v=Yhm63_n7HuU\&t=754s) So, that's transaction monitoring end-to-end. Every payment scored the moment it lands. So, regular money and crypto, all through one engine, each one tied back to a verified person or business. And anything suspicious flagged for your team to review and act on. If you want to try it for yourself, you can head over to didit.me, sign up for free, and send your first transaction today. # How to Read a Verification Result Source: https://docs.didit.me/academy/verification-results Video transcript: every check in a Didit verification result explained - document authenticity, liveness, face match, IP analysis, warnings. Full transcript of **How to Read a Didit Verification Result - Every Check Explained** - Didit Academy video 5 of 10, 14:26. [Watch on YouTube](https://www.youtube.com/watch?v=7htTWCWsl60). Each paragraph links to the exact moment in the video. ## What this video covers [00:03](https://www.youtube.com/watch?v=7htTWCWsl60\&t=3s) Every verification you run in Didit comes back as a detailed result and that result is laid out as a row of tabs across the top of a session. In this video, we're going to go walk through those tabs in order left to right so you know exactly what each check does and what it looks like when one of them fails. And by the end, you'll be able to open any session and read it with confidence from the headline verdict right down to the evidence behind it. [00:30](https://www.youtube.com/watch?v=7htTWCWsl60\&t=30s) So, let's open one up and get stuck in. ## Finding a session [00:33](https://www.youtube.com/watch?v=7htTWCWsl60\&t=33s) Okay, so let's navigate to the user verifications. This is where every session is going to appear from all of your workflows. It's going to be one row per person. And normally you'd filter by status, workflow, or date to find whatever you need, but today we're just going to go straight into a single result. So, I'm just going to click on one of these and open it. So, right here we can see this ## The overview tab [00:55](https://www.youtube.com/watch?v=7htTWCWsl60\&t=55s) is the overview tab. These are collapsible so we can collapse these. We can collapse all the checks if we want if we want to see everything, but honestly they're all up here as well. So, you could see this particular user has passed all of these specific checks. So, if we just head over to overview, we ## Warnings: where to look first [01:13](https://www.youtube.com/watch?v=7htTWCWsl60\&t=73s) can pull that out and you can see we've got a few different tabs here. Now, the most important thing to check out here is the warnings. So, you could see this user is in review and you can see they've been flagged for a duplicate phone number. Okay, so if we check out other people that are in review, we could see the warnings in the overview section might look a little bit different. Based on the flags from the workflow, this particular user has gone through. You could see the database validation and the name mismatch. So, this is where we need to look if we're reviewing a verification and we need to figure out what the issue is and then we can go to the specific section and we can see where these checks actually are and we can look at the data that's been submitted to see if there is indeed a mismatch and what's really going on there. Now, if we remove all of these filters, so I can just come out of here, ## An approved session [02:04](https://www.youtube.com/watch?v=7htTWCWsl60\&t=124s) we can remove these filters. So, I'm going to select all of these and let's see if we go into someone who has been approved, we can see there's there's no major warnings that have been flagged. We can see this has been listed under the warnings, but it's not triggered the in review or the decline. This has actually been approved. We can see this little pill up here and we can actually change these as needed. We'll get into ## A declined session [02:26](https://www.youtube.com/watch?v=7htTWCWsl60\&t=146s) that in a little moment. And what does it look like when someone has been declined? We can see here the warnings, again, the name mismatch. And then up here at the top, we can see proof of address is the one that caused some issues. So, we can come in and take a look at this as well. So, we're going to go through each section one by one so you could see exactly what's happening underneath the hood. So, I'm just clicking into this profile here and you can see the liveness and the face match is where this particular user has been flagged for checking. So, we'll get to that in a moment. But the rest of the ## Session details, vendor data and cost breakdown [03:01](https://www.youtube.com/watch?v=7htTWCWsl60\&t=181s) tabs in the overview section, we've got session details, so you've got the session ID, when it was created, the vendor data. So, we spoke about this in previous videos. The vendor data is a unique identifier for this particular user. This is where all of the \[snorts] checks, all of the verifications and transactions are going to be collected under the specific vendor data. We can see the workflows that this user has gone through for the verification. We've got the contact details here and any tags. I mean, we can we can add a tag here if you want. [03:31](https://www.youtube.com/watch?v=7htTWCWsl60\&t=211s) We can tag people in workflows as well. Now, the total cost breakdown, I believe this this user was imported. You can see here on the left, it was imported, so he hasn't actually gone through a workflow. Let's click this other user here and you can see the workflow that they've gone through and you can see the cost ## ID Verification: authenticity before data [03:48](https://www.youtube.com/watch?v=7htTWCWsl60\&t=228s) breakdown of all the checks this user has completed. So, let's take a look at the ID verification. Now, the main job is not just reading text off the card. It's It's proving the document itself is genuine before anyone trusts a single field on it. So, under the hood, we're running tamper detection, document liveness to catch a screen replay or a printed copy, security feature validation for holograms and watermarks, and a a cross-check between the printed fields and the machine-readable zone, the MRZ, the block of chevron characters at the back that you could see here on this particular ID. Now, once the document is proven authentic, Dedit will read the fields with OCR and lay them out. Here, you can see the personal data. Got the document type, the document number, personal number, issuing state, all of the information that you would find on the ID, including the address data and any additional data in here. And remember, Dedit can read more than 130 languages across 14,000 document types. So, you're going to get clean fields ## The checks list [04:47](https://www.youtube.com/watch?v=7htTWCWsl60\&t=287s) wherever someone presents their ID. So, there is a tab here called checks list. And these are the checks that are running in the background on this specific ID. So, I'm not going to read through all of these. There is a lot here, but this is essentially how Dedit is verifying that this is an authentic ID. So, you don't have to configure any ## Liveness: score, video and quality [05:07](https://www.youtube.com/watch?v=7htTWCWsl60\&t=307s) of this. This is all running in the background. So, the next check is the liveness check. You can see that this particular check is in review. This is what's been flagged. You can see liveness and face match. Now, I will say this is a demo account, so some of this data is not matching. Um you can see the liveness score is it's not 100%, and if we play the liveness video, you could see it's it's not actually the person. [05:30](https://www.youtube.com/watch?v=7htTWCWsl60\&t=330s) This is just a random example. Now, if you were to see this on a on a real user, you would see the the person doing the liveness check, the video, whether it's passive or active. We've got the face quality score and the face luminance score. And the cool thing about Dedit is if you're confused about any of these scores, you can just click this button here and it'll give you an explanation of what this does. We can change the status of any of these checks if we believe that this has been flagged inappropriately, and obviously we can change the overall status of this verification. Again, just like the ID verification, we've got a checks list and there's a bunch of checks here that are all happening in the background, right? And we can hover over these and we can see a little bit more information about each of these checks. And if somebody fails any of these tests, instead of the green ## Face Match [06:16](https://www.youtube.com/watch?v=7htTWCWsl60\&t=376s) tick, there's going to be a red X. So, if we keep going, we've got the face match tab. This is going to match the face on the ID with the face in the liveness check. And you can see here, obviously the similarity score is pretty low because they're not really the same person. And again, we've got a checks list of what's happening in the background there and what this particular check is doing. So, the similarity score is based on the original ID and the liveness image that we've captured. And this is to figure out if the person holding the ID is a genuine owner. Now, we're not going to see this in the dashboard, but there is a face ## Face Search and block lists [06:54](https://www.youtube.com/watch?v=7htTWCWsl60\&t=414s) search. So, beyond matching against the document, Didit searches the same face across all of your other sessions. So, this part only shows when it finds a match. So, if the same face turns up in another session, a grid of matches is going to appear here. And if one of those matched faces is on a block list that you maintain, it's going to be flagged and the session will be declined, which is how a known fraudster gets stopped on site. But on a clean session with no matches, this area stays ## Proof of Address [07:21](https://www.youtube.com/watch?v=7htTWCWsl60\&t=441s) empty, so we're not going to see anything here. Let's move on to proof of address. We can see the document that was submitted and the data that was extracted from this particular document with all of the metadata. So, we've got a checks list here and we can see one of the checks does not have a green tick, meaning that this check was being flagged. And we can see one is in review. Now, that's not enough for this proof of address module to be flicked over to declined, but this is again something that your human reviewer is going to be looking at when they come to a profile that is in review. And a pass here means the code was entered correctly and a failure means the number couldn't be confirmed, and you'll see that reflected in this module here. So, you remember at the top, one of the flags here was duplicate phone number, and now that's probably due to this being a demo ## Phone verification and duplicates [08:08](https://www.youtube.com/watch?v=7htTWCWsl60\&t=488s) account, but you could see when we scroll down under the phone verification, we could see phone matches. Now, this is going to search the phone number on your database, and if it matches anything from a previous user, then this is going to be flagged in this tab here. We can also hover over here. We can see other verification sessions that use the same phone number. This is just an explanation of what this module does. ## Email verification [08:35](https://www.youtube.com/watch?v=7htTWCWsl60\&t=515s) Same for email verification, the user is going to receive a code and put the ## AML screening: sanctions, PEPs and adverse media [08:40](https://www.youtube.com/watch?v=7htTWCWsl60\&t=520s) code, and if everything's good, then this module is also approved. Now, the anti-money laundering, the AML screening, there's quite a lot going on here. This checks the verified person against sanction lists, politically exposed persons, adverse media, and then reports how many matches were found. So, you could see the data that it's using to screen, and we can actually see the list. So, if I open this up, we could see all of the sanction lists here that we can run the checks against. So, narcotics, terrorism, financial crime, everything. And we can see if this user has matched on any of the lists, we could see here the match score, the risk score, and the lists that this user has appeared on and whether it's a false positive or not. Now, a false positive can occur if the name matches somebody on one of those lists. So, this is where we have other information like the date of birth to to cross-reference. We do have a checks list here again. Uh it's pretty short for this particular one, but the the checks against all these lists is doing the heavy lifting here. [09:41](https://www.youtube.com/watch?v=7htTWCWsl60\&t=581s) And if you want to have this person monitored ongoing, where we can check the lists against this user on an ongoing basis, we can actually turn that on. If we keep moving down, we can see ## Device and IP analysis [09:50](https://www.youtube.com/watch?v=7htTWCWsl60\&t=590s) the device IP analysis. So, we have the ID verification document location. So, the actual address from the document. We have the address details here for the proof of address. And then we have the device information. So, the IP address and where that person is actually completing the verification from. And we could see at the bottom the document location versus the proof of address, how far away those distances and those locations are from the verification IP. And we can see all of that on this map. So, we see if we hover over here, we've got the ID verification document location. [10:28](https://www.youtube.com/watch?v=7htTWCWsl60\&t=628s) Got device number one, so they're pretty close. And then we have the proof of address in the US here. Again, this is a demo account, so these details are not particularly accurate, but this just gives you a good understanding of is that person close to where the proof of address and their ID actually is. And here we have the checks list again, and these are all the checks that ID it is doing in the background to decide whether to flag \[snorts] this particular check or not. If we keep going down, we've got database validation. So, if you remember in previous videos, we spoke about database validation. It's a node that you can add in a workflow. And what we can do here is we can run a check. And for this example, we can run ## Database validation: full, partial and no match [11:06](https://www.youtube.com/watch?v=7htTWCWsl60\&t=666s) a check in Argentina, and we can check against a government registry, civil registry, the tax authority, the electoral roll, all of these different directories that we do have access to. You could see we have a match found here. And you could see the source data, the fields that match on the results. So, we've got a full name match and a date of birth match. And if we open up the checks list, we can see one of these checks was flagged. [11:29](https://www.youtube.com/watch?v=7htTWCWsl60\&t=689s) And we can see here the match type. Now, if a full match has been found, it means the identity exists in the registry. Partial match means some fields matched and you should review the rest. And a no match is a strong synthetic identity signal because a fabricated ID number simply isn't in any registry. And this is one of the strongest defenses you have against made-up identities. And again, it runs in the background with no ## Document AI and questionnaires [11:54](https://www.youtube.com/watch?v=7htTWCWsl60\&t=714s) extra steps for the user. Now, moving on, we do have a few other tabs here and these can vary depending on the checks that this particular user has gone through. We can see document AI. This check hasn't run. You can see not started. There are other checks that we do have for questionnaires. If somebody ends up filling out a questionnaire, we could see the answers to those questions in ## The event log [12:15](https://www.youtube.com/watch?v=7htTWCWsl60\&t=735s) the questionnaire tab. And then if we keep on moving down, we've got the events. So, this is a audit trail, a log of all of the events that happened. So, when the session was created, when the session status changed, and each entry carries the device, the IP, the timing, who did it, so you can reconstruct ## Webhook deliveries [12:31](https://www.youtube.com/watch?v=7htTWCWsl60\&t=751s) exactly how a session unfolded. And then finally, at the bottom, we have webhooks. So, webhooks list every delivery Didit attempt to your own endpoint with the response status. We can see 200 here. And we could see the request header, the body, the webhook URL, the status of this particular verification. And we've also got the date here this webhook was sent. So, one thing to note here is that this dashboard can be accessed through the API through the MCP. You can ask Claude to pull all of this data, to pull all of your verifications that are in review that you can analyze inside of ## Resubmission, PDF export and block lists [13:08](https://www.youtube.com/watch?v=7htTWCWsl60\&t=788s) Claude as well. Now, if you take a look at the top here, we've got some breadcrumbs and we can see we can request resubmission. We can download the PDF, which is excellent if you want to have an audit trail or you need to present something in a meeting. Um you can also access this download through the API and you can add this person to a block list. So, that is how you read a verification ## Session chat for your review team [13:30](https://www.youtube.com/watch?v=7htTWCWsl60\&t=810s) result. There's one last thing at the bottom here. We've got a session chat. So, we can actually tag team members, and we can talk about a specific verification result with somebody on our team. So, if we opened up this chat and we put in a message and we tagged someone on our team, that's going to be specific for this particular verification. So, if we do have a question or there's multiple people working on this case, this chat is going to be incredibly useful. [13:55](https://www.youtube.com/watch?v=7htTWCWsl60\&t=835s) So, that's a verification result read the way you'll actually read it, tab by tab, top to bottom. The verdict and the warnings on overview, then each check in turn, and the full audit trail at the end. So, once you've done it on one session, every other session reads the same way. And if you want to try it on your own data, head to didit.me, sign up for free, and open your first result. # Argentina Citizens (AFIP) Source: https://docs.didit.me/api-reference/database-validation/argentina/citizens POST /v3/database-validation/ Verifies input data to the AFIP (Administracion Federal de Ingresos Publicos). Authoritative real-time identity lookup for Argentina. Real-time lookup, pay-per-call.
Verifies input data to the AFIP (Administracion Federal de Ingresos Publicos). Didit exposes this service through `POST /v3/database-validation/` so you can verify the submitted data against the authoritative source and receive normalized match results. ## Coverage * **Coverage:** \~ 90% * **Country:** Argentina * **Service ID:** `arg_citizens` * **Data domain:** Identity * **Category:** Citizenship ## Inputs | Field | Required | Example | | ----------------- | -------: | ------------ | | `first_name` | Yes | `John` | | `last_name` | Yes | `Doe` | | `date_of_birth` | Yes | `1990-01-01` | | `document_number` | Yes | `1111111` | | `vendor_data` | No | `user-1234` | * **Required inputs:** `first_name`, `last_name`, `date_of_birth`, `document_number` * **Optional inputs:** `vendor_data` * **Consent:** Not required * **Workflow availability:** Available in workflow * **Coverage:** \~ 90% * **Price:** \$1.90 per successful query ## Body parameters ISO 3166-1 alpha-3 country code for this database service. Example: `ARG` Array containing this service ID. Pinning the service keeps the request scoped to this exact database. Example: `arg_citizens` Given name to validate. Example: `John` Family name to validate. Example: `Doe` Date of birth in `YYYY-MM-DD` format. Example: `1990-01-01` Document number extracted from or provided by the user. Example: `1111111` Your stable user reference for this person, such as your internal user ID. Didit uses it to link standalone checks to the same end user and reduce duplicate-detection noise. Example: `user-1234` ## Input rules & validation notes * Argentine DNI (7-8 digits) * `document_number` must contain digits only; remove spaces, hyphens, and punctuation before sending the request. * `document_number` must be 7-8 characters long. ## How to call it ```bash cURL theme={null} curl -X POST "https://verification.didit.me/v3/database-validation/" \ -H "x-api-key: YOUR_API_KEY" \ -F "issuing_state=ARG" \ -F "services=arg_citizens" \ -F "vendor_data=user-1234" \ -F "first_name=John" \ -F "last_name=Doe" \ -F "date_of_birth=1990-01-01" \ -F "document_number=1111111" ``` Every successful call returns HTTP `200`. The **`outcome_code`** field tells you what actually happened — distinguishing, for example, a real biometric mismatch (`BIOMETRIC_NO_MATCH`) from a selfie that could not be read (`BIOMETRIC_IMAGE_UNUSABLE`). The `status` shown is the default feature status; your configured [Partial Match / No Match actions](/core-technology/database-validation/database-validation-warnings) can override it. **`MATCH`** — The registry confirmed the identity and every checked field matched. ```json 200 OK — MATCH theme={null} { "request_id": "req_01H…", "status": "Approved", "issuing_state": "ARG", "match_type": "full_match", "validations": [ { "outcome_code": "MATCH", "service_id": "arg_citizens", "service_name": "Argentina Citizens (AFIP)", "source_data": { "date_of_birth": "1990-01-01", "first_name": "John", "full_name": "John Doe", "identification_number": "SAMPLE-ID-12345", "last_name": "Doe", "name_match_score": "1.000", "verifications": { "date_of_birth": true, "full_name": true, "identification_number": true } }, "validation": { "date_of_birth": "full_match", "full_name": "full_match", "identification_number": "full_match" } } ] } ``` **`PARTIAL_MATCH`** — The identification number was found but one or more personal fields (usually name or date of birth) did not fully match. ```json 200 OK — PARTIAL_MATCH theme={null} { "request_id": "req_01H…", "status": "In Review", "issuing_state": "ARG", "match_type": "partial_match", "validations": [ { "outcome_code": "PARTIAL_MATCH", "service_id": "arg_citizens", "service_name": "Argentina Citizens (AFIP)", "source_data": { "date_of_birth": "1990-01-01", "first_name": "John", "full_name": "John Doe", "identification_number": "SAMPLE-ID-12345", "last_name": "Doe", "name_match_score": "1.000", "verifications": { "date_of_birth": true, "full_name": false, "identification_number": true } }, "validation": { "date_of_birth": "full_match", "full_name": "no_match", "identification_number": "full_match" } } ] } ``` **`NO_MATCH`** — The registry returned no match for the submitted data. ```json 200 OK — NO_MATCH theme={null} { "request_id": "req_01H…", "status": "Declined", "issuing_state": "ARG", "match_type": "no_match", "validations": [ { "outcome_code": "NO_MATCH", "service_id": "arg_citizens", "service_name": "Argentina Citizens (AFIP)", "source_data": { "date_of_birth": "NO_MATCH", "full_name": "NO_MATCH", "identification_number": "NO_MATCH" }, "validation": { "date_of_birth": "no_match", "full_name": "no_match", "identification_number": "no_match" } } ] } ``` ## Returned data The exact fields surfaced in `source_data` depend on what the registry returns. The generated example for `arg_citizens` currently documents this normalized shape: * `date_of_birth` * `first_name` * `full_name` * `identification_number` * `last_name` * `name_match_score` ## Pricing & SLAs Argentina Citizens (AFIP) queries are billed only when Didit receives a conclusive result from the validation source. * **Per-call price:** \$1.90 USD. * **Billing:** per successful query. You are not charged when the registry is unreachable, when required fields are missing, or when the request is rejected before reaching the source. * **Latency:** typical p95 \< 2 s. * **Availability:** 99.9% per quarter on Didit's side; downstream source availability varies by country and dataset. ## Continue reading * [Argentina Database Validation overview](/api-reference/database-validation/argentina) * [Database Validation overview](/core-technology/database-validation/overview) * [Outcome Codes](/core-technology/database-validation/database-validation-outcome-codes) # Argentina Credit Bureau Source: https://docs.didit.me/api-reference/database-validation/argentina/credit-bureau POST /v3/database-validation/ Verifies input data against Credit Header data obtained from a Credit Bureau in Argentina. Authoritative real-time identity lookup for Argentina. Real-time lookup, pay-per-call.
Verifies input data against Credit Header data obtained from a Credit Bureau in Argentina. Didit exposes this service through `POST /v3/database-validation/` so you can verify the submitted data against the authoritative source and receive normalized match results. ## Coverage * **Coverage:** \~ 90% * **Country:** Argentina * **Service ID:** `arg_credit_bureau` * **Data domain:** Financial * **Category:** CreditBureau ## Inputs | Field | Required | Example | | ----------------- | -------: | ------------ | | `first_name` | Yes | `John` | | `last_name` | Yes | `Doe` | | `date_of_birth` | Yes | `1990-01-01` | | `document_number` | Yes | `1111111` | | `vendor_data` | No | `user-1234` | * **Required inputs:** `first_name`, `last_name`, `date_of_birth`, `document_number` * **Optional inputs:** `vendor_data` * **Consent:** Not required * **Workflow availability:** Available in workflow * **Coverage:** \~ 90% * **Price:** \$2.15 per successful query ## Body parameters ISO 3166-1 alpha-3 country code for this database service. Example: `ARG` Array containing this service ID. Pinning the service keeps the request scoped to this exact database. Example: `arg_credit_bureau` Given name to validate. Example: `John` Family name to validate. Example: `Doe` Date of birth in `YYYY-MM-DD` format. Example: `1990-01-01` Document number extracted from or provided by the user. Example: `1111111` Your stable user reference for this person, such as your internal user ID. Didit uses it to link standalone checks to the same end user and reduce duplicate-detection noise. Example: `user-1234` ## Input rules & validation notes * Argentine DNI (7-8 digits) * `document_number` must contain digits only; remove spaces, hyphens, and punctuation before sending the request. * `document_number` must be 7-8 characters long. ## How to call it ```bash cURL theme={null} curl -X POST "https://verification.didit.me/v3/database-validation/" \ -H "x-api-key: YOUR_API_KEY" \ -F "issuing_state=ARG" \ -F "services=arg_credit_bureau" \ -F "vendor_data=user-1234" \ -F "first_name=John" \ -F "last_name=Doe" \ -F "date_of_birth=1990-01-01" \ -F "document_number=1111111" ``` Every successful call returns HTTP `200`. The **`outcome_code`** field tells you what actually happened — distinguishing, for example, a real biometric mismatch (`BIOMETRIC_NO_MATCH`) from a selfie that could not be read (`BIOMETRIC_IMAGE_UNUSABLE`). The `status` shown is the default feature status; your configured [Partial Match / No Match actions](/core-technology/database-validation/database-validation-warnings) can override it. **`MATCH`** — The registry confirmed the identity and every checked field matched. ```json 200 OK — MATCH theme={null} { "request_id": "req_01H…", "status": "Approved", "issuing_state": "ARG", "match_type": "full_match", "validations": [ { "outcome_code": "MATCH", "service_id": "arg_credit_bureau", "service_name": "Argentina Credit Bureau", "source_data": { "date_of_birth": "1990-01-01", "first_name": "John", "full_name": "John Doe", "identification_number": "SAMPLE-ID-12345", "last_name": "Doe", "name_match_score": "1.000", "verifications": { "date_of_birth": true, "full_name": true, "identification_number": true } }, "validation": { "date_of_birth": "full_match", "full_name": "full_match", "identification_number": "full_match" } } ] } ``` **`PARTIAL_MATCH`** — The identification number was found but one or more personal fields (usually name or date of birth) did not fully match. ```json 200 OK — PARTIAL_MATCH theme={null} { "request_id": "req_01H…", "status": "In Review", "issuing_state": "ARG", "match_type": "partial_match", "validations": [ { "outcome_code": "PARTIAL_MATCH", "service_id": "arg_credit_bureau", "service_name": "Argentina Credit Bureau", "source_data": { "date_of_birth": "1990-01-01", "first_name": "John", "full_name": "John Doe", "identification_number": "SAMPLE-ID-12345", "last_name": "Doe", "name_match_score": "1.000", "verifications": { "date_of_birth": true, "full_name": false, "identification_number": true } }, "validation": { "date_of_birth": "full_match", "full_name": "no_match", "identification_number": "full_match" } } ] } ``` **`NO_MATCH`** — The registry returned no match for the submitted data. ```json 200 OK — NO_MATCH theme={null} { "request_id": "req_01H…", "status": "Declined", "issuing_state": "ARG", "match_type": "no_match", "validations": [ { "outcome_code": "NO_MATCH", "service_id": "arg_credit_bureau", "service_name": "Argentina Credit Bureau", "source_data": { "date_of_birth": "NO_MATCH", "full_name": "NO_MATCH", "identification_number": "NO_MATCH" }, "validation": { "date_of_birth": "no_match", "full_name": "no_match", "identification_number": "no_match" } } ] } ``` ## Returned data The exact fields surfaced in `source_data` depend on what the registry returns. The generated example for `arg_credit_bureau` currently documents this normalized shape: * `date_of_birth` * `first_name` * `full_name` * `identification_number` * `last_name` * `name_match_score` ## Pricing & SLAs Argentina Credit Bureau queries are billed only when Didit receives a conclusive result from the validation source. * **Per-call price:** \$2.15 USD. * **Billing:** per successful query. You are not charged when the registry is unreachable, when required fields are missing, or when the request is rejected before reaching the source. * **Latency:** typical p95 \< 2 s. * **Availability:** 99.9% per quarter on Didit's side; downstream source availability varies by country and dataset. ## Continue reading * [Argentina Database Validation overview](/api-reference/database-validation/argentina) * [Database Validation overview](/core-technology/database-validation/overview) * [Outcome Codes](/core-technology/database-validation/database-validation-outcome-codes) # Argentina - DNI verification (RENAPER) Source: https://docs.didit.me/api-reference/database-validation/argentina/renaper POST /v3/database-validation/ Verifies Argentine DNI against the official RENAPER civil registry, with biometric face-match against the photo on file. 100% population coverage. Authoritative real-time identity lookup for Argentina. Real-time lookup, pay-per-call.
Verifies Argentine DNI against the official RENAPER civil registry, with biometric face-match against the photo on file. 100% population coverage. Didit exposes this service through `POST /v3/database-validation/` so you can verify the submitted data against the authoritative source and receive normalized match results. ## Coverage * **Coverage:** — * **Country:** Argentina * **Service ID:** `arg_renaper` * **Data domain:** Identity * **Category:** NationalIDRegistry ## Inputs | Field | Required | Example | | ----------------- | -------: | --------------- | | `document_number` | Yes | `1111111` | | `selfie` | Yes | `@./selfie.jpg` | | `gender` | Yes | `M` | | `first_name` | No | `John` | | `last_name` | No | `Doe` | | `vendor_data` | No | `user-1234` | * **Required inputs:** `document_number`, `selfie`, `gender` * **Optional inputs:** `first_name`, `last_name`, `vendor_data` * **Consent:** Not required * **Workflow availability:** Available in workflow * **Coverage:** — * **Price:** \$0.20 per successful query ## Body parameters ISO 3166-1 alpha-3 country code for this database service. Example: `ARG` Array containing this service ID. Pinning the service keeps the request scoped to this exact database. Example: `arg_renaper` Document number extracted from or provided by the user. Example: `1111111` Selfie image file to upload for biometric database validation. Accepted formats: JPEG, PNG, or WebP. Example: `@./selfie.jpg` Gender value, when required by the database. Allowed values: `M` (male), `F` (female), `X` (other or unknown). Example: `M` Given name to validate. Example: `John` Family name to validate. Example: `Doe` Your stable user reference for this person, such as your internal user ID. Didit uses it to link standalone checks to the same end user and reduce duplicate-detection noise. Example: `user-1234` ## Input rules & validation notes * Argentine DNI (7-8 digits) * `document_number` must contain digits only; remove spaces, hyphens, and punctuation before sending the request. * `document_number` must be 7-8 characters long. ## How to call it ```bash cURL theme={null} curl -X POST "https://verification.didit.me/v3/database-validation/" \ -H "x-api-key: YOUR_API_KEY" \ -F "issuing_state=ARG" \ -F "services=arg_renaper" \ -F "vendor_data=user-1234" \ -F "document_number=1111111" \ -F "selfie=@./selfie.jpg" \ -F "gender=M" ``` Every successful call returns HTTP `200`. The **`outcome_code`** field tells you what actually happened — distinguishing, for example, a real biometric mismatch (`BIOMETRIC_NO_MATCH`) from a selfie that could not be read (`BIOMETRIC_IMAGE_UNUSABLE`). The `status` shown is the default feature status; your configured [Partial Match / No Match actions](/core-technology/database-validation/database-validation-warnings) can override it. **`MATCH`** — The registry confirmed the identity and every checked field matched. ```json 200 OK — MATCH theme={null} { "request_id": "req_01H…", "status": "Approved", "issuing_state": "ARG", "match_type": "full_match", "validations": [ { "outcome_code": "MATCH", "service_id": "arg_renaper", "service_name": "Argentina - DNI verification (RENAPER)", "source_data": { "banks": "sample_value", "date_of_birth": "1990-01-01", "face_match_score": "0.990", "first_name": "John", "full_name": "John Doe", "highest_position": "sample_value", "identification_number": "SAMPLE-ID-12345", "last_name": "Doe", "last_position": "sample_value", "rejected_checks": "sample_value", "sit_1_since": "sample_value", "tax_id": "SAMPLE-12345", "tax_id_type": "SAMPLE-12345" }, "validation": { "identification_number": "full_match" } } ] } ``` **`NO_MATCH`** — The registry returned no match for the submitted data. ```json 200 OK — NO_MATCH theme={null} { "request_id": "req_01H…", "status": "Declined", "issuing_state": "ARG", "match_type": "no_match", "validations": [ { "outcome_code": "NO_MATCH", "service_id": "arg_renaper", "service_name": "Argentina - DNI verification (RENAPER)", "source_data": { "identification_number": "NO_MATCH" }, "validation": { "identification_number": "no_match" } } ] } ``` **`BIOMETRIC_NO_MATCH`** — The face-match score was below the acceptance threshold - the selfie is not the same person as the registry photo. ```json 200 OK — BIOMETRIC_NO_MATCH theme={null} { "request_id": "req_01H…", "status": "Declined", "issuing_state": "ARG", "match_type": "no_match", "validations": [ { "outcome_code": "BIOMETRIC_NO_MATCH", "service_id": "arg_renaper", "service_name": "Argentina - DNI verification (RENAPER)", "source_data": { "identification_number": "NO_MATCH" }, "validation": { "identification_number": "no_match" } } ] } ``` **`BIOMETRIC_IMAGE_UNUSABLE`** — The selfie could not be processed (empty, no face, low quality, or the registry could not read it). Prompt the user to retake the selfie. ```json 200 OK — BIOMETRIC_IMAGE_UNUSABLE theme={null} { "request_id": "req_01H…", "status": "In Review", "issuing_state": "ARG", "match_type": "no_match", "validations": [ { "outcome_code": "BIOMETRIC_IMAGE_UNUSABLE", "service_id": "arg_renaper", "service_name": "Argentina - DNI verification (RENAPER)", "source_data": { "identification_number": "NO_MATCH" }, "validation": { "identification_number": "no_match" } } ] } ``` ## Returned data The exact fields surfaced in `source_data` depend on what the registry returns. The generated example for `arg_renaper` currently documents this normalized shape: * `banks` * `date_of_birth` * `face_match_score` * `first_name` * `full_name` * `highest_position` * `identification_number` * `last_name` * `last_position` * `rejected_checks` * `sit_1_since` * `tax_id` * `tax_id_type` ## Pricing & SLAs Argentina - DNI verification (RENAPER) queries are billed only when Didit receives a conclusive result from the validation source. * **Per-call price:** \$0.20 USD. * **Billing:** per successful query. You are not charged when the registry is unreachable, when required fields are missing, or when the request is rejected before reaching the source. * **Latency:** typical p95 \< 2 s. * **Availability:** 99.9% per quarter on Didit's side; downstream source availability varies by country and dataset. ## Continue reading * [Argentina Database Validation overview](/api-reference/database-validation/argentina) * [Database Validation overview](/core-technology/database-validation/overview) * [Outcome Codes](/core-technology/database-validation/database-validation-outcome-codes) # Australia - DVS - Birth Certificate Source: https://docs.didit.me/api-reference/database-validation/australia/birth-certificate POST /v3/database-validation/ Verifies input data against the Document Verification Service (DVS). Authoritative real-time identity lookup for Australia. Real-time lookup, pay-per-call.
Verifies input data against the Document Verification Service (DVS). Didit exposes this service through `POST /v3/database-validation/` so you can verify the submitted data against the authoritative source and receive normalized match results. ## Coverage * **Coverage:** 100%\* * **Country:** Australia * **Service ID:** `aus_birth_certificate` * **Data domain:** Identity * **Category:** BirthRecord ## Inputs | Field | Required | Example | | --------------------------- | -------: | -------------------- | | `first_name` | Yes | `John` | | `last_name` | Yes | `Doe` | | `date_of_birth` | Yes | `1990-01-01` | | `birth_registration_number` | Yes | `SAMPLE-BIRTH-12345` | | `birth_registration_date` | Yes | `1990-01-01` | | `birth_registration_state` | Yes | `Sample State` | | `middle_name` | No | `Demo` | | `vendor_data` | No | `user-1234` | * **Required inputs:** `first_name`, `last_name`, `date_of_birth`, `birth_registration_number`, `birth_registration_date`, `birth_registration_state` * **Optional inputs:** `middle_name`, `vendor_data` * **Consent:** Required * **Workflow availability:** Available in workflow with field mapping * **Coverage:** 100%\* * **Price:** \$0.45 per successful query In a workflow, `birth_registration_date` and `birth_registration_state` are not printed on an identity document, so no step produces them on their own. Collect them from a Questionnaire answer, a Document AI extraction field, or a value you send when you create the session, and map each one on the Database Validation step. Until they are mapped the workflow editor shows this service disabled and names the missing input; at run time a missing input means the check is skipped before any query, so you are never billed for a database that could not be asked. ## Body parameters ISO 3166-1 alpha-3 country code for this database service. Example: `AUS` Array containing this service ID. Pinning the service keeps the request scoped to this exact database. Example: `aus_birth_certificate` Explicit end-user consent for this service. Example: `true` Given name to validate. Example: `John` Family name to validate. Example: `Doe` Date of birth in `YYYY-MM-DD` format. Example: `1990-01-01` `birth_registration_number` value required by this database service. Example: `SAMPLE-BIRTH-12345` `birth_registration_date` value required by this database service. Example: `1990-01-01` `birth_registration_state` value required by this database service. Example: `Sample State` Middle name, when available. Example: `Demo` Your stable user reference for this person, such as your internal user ID. Didit uses it to link standalone checks to the same end user and reduce duplicate-detection noise. Example: `user-1234` ## Input rules & validation notes * Send the fields listed above exactly as captured from the user or document. * Didit validates required fields before calling the database. Requests rejected before source lookup are not charged. ## How to call it ```bash cURL theme={null} curl -X POST "https://verification.didit.me/v3/database-validation/" \ -H "x-api-key: YOUR_API_KEY" \ -F "issuing_state=AUS" \ -F "services=aus_birth_certificate" \ -F "vendor_data=user-1234" \ -F "consent=true" \ -F "first_name=John" \ -F "last_name=Doe" \ -F "date_of_birth=1990-01-01" \ -F "birth_registration_number=SAMPLE-BIRTH-12345" \ -F "birth_registration_date=1990-01-01" \ -F "birth_registration_state=Sample State" ``` Every successful call returns HTTP `200`. The **`outcome_code`** field tells you what actually happened — distinguishing, for example, a real biometric mismatch (`BIOMETRIC_NO_MATCH`) from a selfie that could not be read (`BIOMETRIC_IMAGE_UNUSABLE`). The `status` shown is the default feature status; your configured [Partial Match / No Match actions](/core-technology/database-validation/database-validation-warnings) can override it. **`MATCH`** — The registry confirmed the identity and every checked field matched. ```json 200 OK — MATCH theme={null} { "request_id": "req_01H…", "status": "Approved", "issuing_state": "AUS", "match_type": "full_match", "validations": [ { "outcome_code": "MATCH", "service_id": "aus_birth_certificate", "service_name": "Australia - DVS - Birth Certificate", "source_data": { "date_of_birth": "1990-01-01", "first_name": "John", "identification_number": "SAMPLE-ID-12345", "last_name": "Doe", "middle_name": "Demo" }, "validation": { "date_of_birth": "full_match", "full_name": "full_match", "identification_number": "full_match" } } ] } ``` **`PARTIAL_MATCH`** — The identification number was found but one or more personal fields (usually name or date of birth) did not fully match. ```json 200 OK — PARTIAL_MATCH theme={null} { "request_id": "req_01H…", "status": "In Review", "issuing_state": "AUS", "match_type": "partial_match", "validations": [ { "outcome_code": "PARTIAL_MATCH", "service_id": "aus_birth_certificate", "service_name": "Australia - DVS - Birth Certificate", "source_data": { "date_of_birth": "1990-01-01", "first_name": "John", "identification_number": "SAMPLE-ID-12345", "last_name": "Doe", "middle_name": "Demo" }, "validation": { "date_of_birth": "full_match", "full_name": "no_match", "identification_number": "full_match" } } ] } ``` **`NO_MATCH`** — The registry returned no match for the submitted data. ```json 200 OK — NO_MATCH theme={null} { "request_id": "req_01H…", "status": "Declined", "issuing_state": "AUS", "match_type": "no_match", "validations": [ { "outcome_code": "NO_MATCH", "service_id": "aus_birth_certificate", "service_name": "Australia - DVS - Birth Certificate", "source_data": { "date_of_birth": "NO_MATCH", "full_name": "NO_MATCH", "identification_number": "NO_MATCH" }, "validation": { "date_of_birth": "no_match", "full_name": "no_match", "identification_number": "no_match" } } ] } ``` ## Returned data The exact fields surfaced in `source_data` depend on what the registry returns. The generated example for `aus_birth_certificate` currently documents this normalized shape: * `date_of_birth` * `first_name` * `identification_number` * `last_name` * `middle_name` ## Pricing & SLAs Australia - DVS - Birth Certificate queries are billed only when Didit receives a conclusive result from the validation source. * **Per-call price:** \$0.45 USD. * **Billing:** per successful query. You are not charged when the registry is unreachable, when required fields are missing, or when the request is rejected before reaching the source. * **Latency:** typical p95 \< 2 s. * **Availability:** 99.9% per quarter on Didit's side; downstream source availability varies by country and dataset. ## Continue reading * [Australia Database Validation overview](/api-reference/database-validation/australia) * [Database Validation overview](/core-technology/database-validation/overview) * [Outcome Codes](/core-technology/database-validation/database-validation-outcome-codes) # Australia - DVS - Centrelink Card Source: https://docs.didit.me/api-reference/database-validation/australia/centrelink-card POST /v3/database-validation/ Verifies input data against the Document Verification Service (DVS). Authoritative real-time identity lookup for Australia. Real-time lookup, pay-per-call.
Verifies input data against the Document Verification Service (DVS). Didit exposes this service through `POST /v3/database-validation/` so you can verify the submitted data against the authoritative source and receive normalized match results. ## Coverage * **Coverage:** 100%\* * **Country:** Australia * **Service ID:** `aus_centrelink_card` * **Data domain:** Government * **Category:** Government ## Inputs | Field | Required | Example | | ---------------------- | -------: | ------------ | | `first_name` | Yes | `John` | | `last_name` | Yes | `Doe` | | `date_of_birth` | Yes | `1990-01-01` | | `medicare_card_number` | Yes | `1111111111` | | `middle_name` | No | `Demo` | | `vendor_data` | No | `user-1234` | * **Required inputs:** `first_name`, `last_name`, `date_of_birth`, `medicare_card_number` * **Optional inputs:** `middle_name`, `vendor_data` * **Consent:** Required * **Workflow availability:** Available in workflow * **Coverage:** 100%\* * **Price:** \$0.45 per successful query ## Body parameters ISO 3166-1 alpha-3 country code for this database service. Example: `AUS` Array containing this service ID. Pinning the service keeps the request scoped to this exact database. Example: `aus_centrelink_card` Explicit end-user consent for this service. Example: `true` Given name to validate. Example: `John` Family name to validate. Example: `Doe` Date of birth in `YYYY-MM-DD` format. Example: `1990-01-01` Medicare card number. Example: `1111111111` Middle name, when available. Example: `Demo` Your stable user reference for this person, such as your internal user ID. Didit uses it to link standalone checks to the same end user and reduce duplicate-detection noise. Example: `user-1234` ## Input rules & validation notes * Australian Medicare card number (exactly 10 digits) * `medicare_card_number` must contain digits only; remove spaces, hyphens, and punctuation before sending the request. * `medicare_card_number` must be exactly 10 characters long. ## How to call it ```bash cURL theme={null} curl -X POST "https://verification.didit.me/v3/database-validation/" \ -H "x-api-key: YOUR_API_KEY" \ -F "issuing_state=AUS" \ -F "services=aus_centrelink_card" \ -F "vendor_data=user-1234" \ -F "consent=true" \ -F "first_name=John" \ -F "last_name=Doe" \ -F "date_of_birth=1990-01-01" \ -F "medicare_card_number=1111111111" ``` Every successful call returns HTTP `200`. The **`outcome_code`** field tells you what actually happened — distinguishing, for example, a real biometric mismatch (`BIOMETRIC_NO_MATCH`) from a selfie that could not be read (`BIOMETRIC_IMAGE_UNUSABLE`). The `status` shown is the default feature status; your configured [Partial Match / No Match actions](/core-technology/database-validation/database-validation-warnings) can override it. **`MATCH`** — The registry confirmed the identity and every checked field matched. ```json 200 OK — MATCH theme={null} { "request_id": "req_01H…", "status": "Approved", "issuing_state": "AUS", "match_type": "full_match", "validations": [ { "outcome_code": "MATCH", "service_id": "aus_centrelink_card", "service_name": "Australia - DVS - Centrelink Card", "source_data": { "date_of_birth": "1990-01-01", "first_name": "John", "identification_number": "SAMPLE-ID-12345", "last_name": "Doe", "middle_name": "Demo" }, "validation": { "date_of_birth": "full_match", "full_name": "full_match", "identification_number": "full_match" } } ] } ``` **`PARTIAL_MATCH`** — The identification number was found but one or more personal fields (usually name or date of birth) did not fully match. ```json 200 OK — PARTIAL_MATCH theme={null} { "request_id": "req_01H…", "status": "In Review", "issuing_state": "AUS", "match_type": "partial_match", "validations": [ { "outcome_code": "PARTIAL_MATCH", "service_id": "aus_centrelink_card", "service_name": "Australia - DVS - Centrelink Card", "source_data": { "date_of_birth": "1990-01-01", "first_name": "John", "identification_number": "SAMPLE-ID-12345", "last_name": "Doe", "middle_name": "Demo" }, "validation": { "date_of_birth": "full_match", "full_name": "no_match", "identification_number": "full_match" } } ] } ``` **`NO_MATCH`** — The registry returned no match for the submitted data. ```json 200 OK — NO_MATCH theme={null} { "request_id": "req_01H…", "status": "Declined", "issuing_state": "AUS", "match_type": "no_match", "validations": [ { "outcome_code": "NO_MATCH", "service_id": "aus_centrelink_card", "service_name": "Australia - DVS - Centrelink Card", "source_data": { "date_of_birth": "NO_MATCH", "full_name": "NO_MATCH", "identification_number": "NO_MATCH" }, "validation": { "date_of_birth": "no_match", "full_name": "no_match", "identification_number": "no_match" } } ] } ``` ## Returned data The exact fields surfaced in `source_data` depend on what the registry returns. The generated example for `aus_centrelink_card` currently documents this normalized shape: * `date_of_birth` * `first_name` * `identification_number` * `last_name` * `middle_name` ## Pricing & SLAs Australia - DVS - Centrelink Card queries are billed only when Didit receives a conclusive result from the validation source. * **Per-call price:** \$0.45 USD. * **Billing:** per successful query. You are not charged when the registry is unreachable, when required fields are missing, or when the request is rejected before reaching the source. * **Latency:** typical p95 \< 2 s. * **Availability:** 99.9% per quarter on Didit's side; downstream source availability varies by country and dataset. ## Continue reading * [Australia Database Validation overview](/api-reference/database-validation/australia) * [Database Validation overview](/core-technology/database-validation/overview) * [Outcome Codes](/core-technology/database-validation/database-validation-outcome-codes) # Australia - DVS – Change of Name Certificate Source: https://docs.didit.me/api-reference/database-validation/australia/change-of-name-certificate POST /v3/database-validation/ Verifies input data against the Document Verification Service (DVS). Authoritative real-time identity lookup for Australia. Real-time lookup, pay-per-call.
Verifies input data against the Document Verification Service (DVS). Didit exposes this service through `POST /v3/database-validation/` so you can verify the submitted data against the authoritative source and receive normalized match results. ## Coverage * **Coverage:** 100%\* * **Country:** Australia * **Service ID:** `aus_change_of_name_certificate` * **Data domain:** Identity * **Category:** CivilRegistry ## Inputs | Field | Required | Example | | ----------------------------------- | -------: | ------------------ | | `first_name` | Yes | `John` | | `last_name` | Yes | `Doe` | | `date_of_birth` | Yes | `1990-01-01` | | `change_of_name_certificate_number` | Yes | `SAMPLE-CON-12345` | | `vendor_data` | No | `user-1234` | * **Required inputs:** `first_name`, `last_name`, `date_of_birth`, `change_of_name_certificate_number` * **Optional inputs:** `vendor_data` * **Consent:** Required * **Workflow availability:** Available in workflow with field mapping * **Coverage:** 100%\* * **Price:** \$0.45 per successful query In a workflow, `change_of_name_certificate_number` is not printed on an identity document, so no step produces it on its own. Collect it from a Questionnaire answer, a Document AI extraction field, or a value you send when you create the session, and map it on the Database Validation step. Until it is mapped the workflow editor shows this service disabled and names the missing input; at run time a missing input means the check is skipped before any query, so you are never billed for a database that could not be asked. ## Body parameters ISO 3166-1 alpha-3 country code for this database service. Example: `AUS` Array containing this service ID. Pinning the service keeps the request scoped to this exact database. Example: `aus_change_of_name_certificate` Explicit end-user consent for this service. Example: `true` Given name to validate. Example: `John` Family name to validate. Example: `Doe` Date of birth in `YYYY-MM-DD` format. Example: `1990-01-01` `change_of_name_certificate_number` value required by this database service. Example: `SAMPLE-CON-12345` Your stable user reference for this person, such as your internal user ID. Didit uses it to link standalone checks to the same end user and reduce duplicate-detection noise. Example: `user-1234` ## Input rules & validation notes * Send the fields listed above exactly as captured from the user or document. * Didit validates required fields before calling the database. Requests rejected before source lookup are not charged. ## How to call it ```bash cURL theme={null} curl -X POST "https://verification.didit.me/v3/database-validation/" \ -H "x-api-key: YOUR_API_KEY" \ -F "issuing_state=AUS" \ -F "services=aus_change_of_name_certificate" \ -F "vendor_data=user-1234" \ -F "consent=true" \ -F "first_name=John" \ -F "last_name=Doe" \ -F "date_of_birth=1990-01-01" \ -F "change_of_name_certificate_number=SAMPLE-CON-12345" ``` Every successful call returns HTTP `200`. The **`outcome_code`** field tells you what actually happened — distinguishing, for example, a real biometric mismatch (`BIOMETRIC_NO_MATCH`) from a selfie that could not be read (`BIOMETRIC_IMAGE_UNUSABLE`). The `status` shown is the default feature status; your configured [Partial Match / No Match actions](/core-technology/database-validation/database-validation-warnings) can override it. **`MATCH`** — The registry confirmed the identity and every checked field matched. ```json 200 OK — MATCH theme={null} { "request_id": "req_01H…", "status": "Approved", "issuing_state": "AUS", "match_type": "full_match", "validations": [ { "outcome_code": "MATCH", "service_id": "aus_change_of_name_certificate", "service_name": "Australia - DVS – Change of Name Certificate", "source_data": { "date_of_birth": "1990-01-01", "first_name": "John", "identification_number": "SAMPLE-ID-12345", "last_name": "Doe" }, "validation": { "date_of_birth": "full_match", "full_name": "full_match", "identification_number": "full_match" } } ] } ``` **`PARTIAL_MATCH`** — The identification number was found but one or more personal fields (usually name or date of birth) did not fully match. ```json 200 OK — PARTIAL_MATCH theme={null} { "request_id": "req_01H…", "status": "In Review", "issuing_state": "AUS", "match_type": "partial_match", "validations": [ { "outcome_code": "PARTIAL_MATCH", "service_id": "aus_change_of_name_certificate", "service_name": "Australia - DVS – Change of Name Certificate", "source_data": { "date_of_birth": "1990-01-01", "first_name": "John", "identification_number": "SAMPLE-ID-12345", "last_name": "Doe" }, "validation": { "date_of_birth": "full_match", "full_name": "no_match", "identification_number": "full_match" } } ] } ``` **`NO_MATCH`** — The registry returned no match for the submitted data. ```json 200 OK — NO_MATCH theme={null} { "request_id": "req_01H…", "status": "Declined", "issuing_state": "AUS", "match_type": "no_match", "validations": [ { "outcome_code": "NO_MATCH", "service_id": "aus_change_of_name_certificate", "service_name": "Australia - DVS – Change of Name Certificate", "source_data": { "date_of_birth": "NO_MATCH", "full_name": "NO_MATCH", "identification_number": "NO_MATCH" }, "validation": { "date_of_birth": "no_match", "full_name": "no_match", "identification_number": "no_match" } } ] } ``` ## Returned data The exact fields surfaced in `source_data` depend on what the registry returns. The generated example for `aus_change_of_name_certificate` currently documents this normalized shape: * `date_of_birth` * `first_name` * `identification_number` * `last_name` ## Pricing & SLAs Australia - DVS – Change of Name Certificate queries are billed only when Didit receives a conclusive result from the validation source. * **Per-call price:** \$0.45 USD. * **Billing:** per successful query. You are not charged when the registry is unreachable, when required fields are missing, or when the request is rejected before reaching the source. * **Latency:** typical p95 \< 2 s. * **Availability:** 99.9% per quarter on Didit's side; downstream source availability varies by country and dataset. ## Continue reading * [Australia Database Validation overview](/api-reference/database-validation/australia) * [Database Validation overview](/core-technology/database-validation/overview) * [Outcome Codes](/core-technology/database-validation/database-validation-outcome-codes) # Australia - DVS – Citizenship Certificate Source: https://docs.didit.me/api-reference/database-validation/australia/citizenship-certificate POST /v3/database-validation/ Verifies input data against the Document Verification Service (DVS). Authoritative real-time identity lookup for Australia. Real-time lookup, pay-per-call.
Verifies input data against the Document Verification Service (DVS). Didit exposes this service through `POST /v3/database-validation/` so you can verify the submitted data against the authoritative source and receive normalized match results. ## Coverage * **Coverage:** 100%\* * **Country:** Australia * **Service ID:** `aus_citizenship_certificate` * **Data domain:** Identity * **Category:** Citizenship ## Inputs | Field | Required | Example | | -------------------------------- | -------: | ------------------- | | `first_name` | Yes | `John` | | `last_name` | Yes | `Doe` | | `date_of_birth` | Yes | `1990-01-01` | | `citizenship_certificate_number` | Yes | `SAMPLE-CERT-12345` | | `middle_name` | No | `Demo` | | `vendor_data` | No | `user-1234` | * **Required inputs:** `first_name`, `last_name`, `date_of_birth`, `citizenship_certificate_number` * **Optional inputs:** `middle_name`, `vendor_data` * **Consent:** Required * **Workflow availability:** Available in workflow with field mapping * **Coverage:** 100%\* * **Price:** \$0.45 per successful query In a workflow, `citizenship_certificate_number` is not printed on an identity document, so no step produces it on its own. Collect it from a Questionnaire answer, a Document AI extraction field, or a value you send when you create the session, and map it on the Database Validation step. Until it is mapped the workflow editor shows this service disabled and names the missing input; at run time a missing input means the check is skipped before any query, so you are never billed for a database that could not be asked. ## Body parameters ISO 3166-1 alpha-3 country code for this database service. Example: `AUS` Array containing this service ID. Pinning the service keeps the request scoped to this exact database. Example: `aus_citizenship_certificate` Explicit end-user consent for this service. Example: `true` Given name to validate. Example: `John` Family name to validate. Example: `Doe` Date of birth in `YYYY-MM-DD` format. Example: `1990-01-01` `citizenship_certificate_number` value required by this database service. Example: `SAMPLE-CERT-12345` Middle name, when available. Example: `Demo` Your stable user reference for this person, such as your internal user ID. Didit uses it to link standalone checks to the same end user and reduce duplicate-detection noise. Example: `user-1234` ## Input rules & validation notes * Send the fields listed above exactly as captured from the user or document. * Didit validates required fields before calling the database. Requests rejected before source lookup are not charged. ## How to call it ```bash cURL theme={null} curl -X POST "https://verification.didit.me/v3/database-validation/" \ -H "x-api-key: YOUR_API_KEY" \ -F "issuing_state=AUS" \ -F "services=aus_citizenship_certificate" \ -F "vendor_data=user-1234" \ -F "consent=true" \ -F "first_name=John" \ -F "last_name=Doe" \ -F "date_of_birth=1990-01-01" \ -F "citizenship_certificate_number=SAMPLE-CERT-12345" ``` Every successful call returns HTTP `200`. The **`outcome_code`** field tells you what actually happened — distinguishing, for example, a real biometric mismatch (`BIOMETRIC_NO_MATCH`) from a selfie that could not be read (`BIOMETRIC_IMAGE_UNUSABLE`). The `status` shown is the default feature status; your configured [Partial Match / No Match actions](/core-technology/database-validation/database-validation-warnings) can override it. **`MATCH`** — The registry confirmed the identity and every checked field matched. ```json 200 OK — MATCH theme={null} { "request_id": "req_01H…", "status": "Approved", "issuing_state": "AUS", "match_type": "full_match", "validations": [ { "outcome_code": "MATCH", "service_id": "aus_citizenship_certificate", "service_name": "Australia - DVS – Citizenship Certificate", "source_data": { "date_of_birth": "1990-01-01", "first_name": "John", "identification_number": "SAMPLE-ID-12345", "last_name": "Doe", "middle_name": "Demo" }, "validation": { "date_of_birth": "full_match", "full_name": "full_match", "identification_number": "full_match" } } ] } ``` **`PARTIAL_MATCH`** — The identification number was found but one or more personal fields (usually name or date of birth) did not fully match. ```json 200 OK — PARTIAL_MATCH theme={null} { "request_id": "req_01H…", "status": "In Review", "issuing_state": "AUS", "match_type": "partial_match", "validations": [ { "outcome_code": "PARTIAL_MATCH", "service_id": "aus_citizenship_certificate", "service_name": "Australia - DVS – Citizenship Certificate", "source_data": { "date_of_birth": "1990-01-01", "first_name": "John", "identification_number": "SAMPLE-ID-12345", "last_name": "Doe", "middle_name": "Demo" }, "validation": { "date_of_birth": "full_match", "full_name": "no_match", "identification_number": "full_match" } } ] } ``` **`NO_MATCH`** — The registry returned no match for the submitted data. ```json 200 OK — NO_MATCH theme={null} { "request_id": "req_01H…", "status": "Declined", "issuing_state": "AUS", "match_type": "no_match", "validations": [ { "outcome_code": "NO_MATCH", "service_id": "aus_citizenship_certificate", "service_name": "Australia - DVS – Citizenship Certificate", "source_data": { "date_of_birth": "NO_MATCH", "full_name": "NO_MATCH", "identification_number": "NO_MATCH" }, "validation": { "date_of_birth": "no_match", "full_name": "no_match", "identification_number": "no_match" } } ] } ``` ## Returned data The exact fields surfaced in `source_data` depend on what the registry returns. The generated example for `aus_citizenship_certificate` currently documents this normalized shape: * `date_of_birth` * `first_name` * `identification_number` * `last_name` * `middle_name` ## Pricing & SLAs Australia - DVS – Citizenship Certificate queries are billed only when Didit receives a conclusive result from the validation source. * **Per-call price:** \$0.45 USD. * **Billing:** per successful query. You are not charged when the registry is unreachable, when required fields are missing, or when the request is rejected before reaching the source. * **Latency:** typical p95 \< 2 s. * **Availability:** 99.9% per quarter on Didit's side; downstream source availability varies by country and dataset. ## Continue reading * [Australia Database Validation overview](/api-reference/database-validation/australia) * [Database Validation overview](/core-technology/database-validation/overview) * [Outcome Codes](/core-technology/database-validation/database-validation-outcome-codes) # Australia Credit Bureau Source: https://docs.didit.me/api-reference/database-validation/australia/credit-bureau POST /v3/database-validation/ Verifies input data against Credit Header data obtained from the largest Credit Bureau in Australia. Authoritative real-time identity lookup for Australia. Real-time lookup, pay-per-call.
Verifies input data against Credit Header data obtained from the largest Credit Bureau in Australia. Didit exposes this service through `POST /v3/database-validation/` so you can verify the submitted data against the authoritative source and receive normalized match results. ## Coverage * **Coverage:** \~ 75% * **Country:** Australia * **Service ID:** `aus_credit_bureau` * **Data domain:** Financial * **Category:** CreditBureau ## Inputs | Field | Required | Example | | --------------------- | -------: | ---------------------- | | `first_name` | Yes | `John` | | `last_name` | Yes | `Doe` | | `date_of_birth` | Yes | `1990-01-01` | | `address.street_1` | Yes | `123 Sample Street` | | `address.postal_code` | Yes | `10001` | | `address.street_2` | No | `Unit 4` | | `address.city` | No | `Sample City` | | `address.region` | No | `Sample State` | | `phone` | No | `+15550101000` | | `email` | No | `john.doe@example.com` | | `vendor_data` | No | `user-1234` | * **Required inputs:** `first_name`, `last_name`, `date_of_birth`, `address.street_1`, `address.postal_code` * **Optional inputs:** `address.street_2`, `address.city`, `address.region`, `phone`, `email`, `vendor_data` * **Consent:** Required * **Workflow availability:** Available in workflow * **Coverage:** \~ 75% * **Price:** \$0.70 per successful query ## Body parameters ISO 3166-1 alpha-3 country code for this database service. Example: `AUS` Array containing this service ID. Pinning the service keeps the request scoped to this exact database. Example: `aus_credit_bureau` Explicit end-user consent for this service. Example: `true` Given name to validate. Example: `John` Family name to validate. Example: `Doe` Date of birth in `YYYY-MM-DD` format. Example: `1990-01-01` Structured residential address object. Use `street_1`, `street_2`, `city`, `region`, `postal_code`, and `country`. A complete legacy address string is still accepted but not recommended. Example: `{"street_1":"123 Sample Street","street_2":"Unit 4","city":"Sample City","region":"Sample State","postal_code":"10001","country":"US"}` Phone number in international format. Example: `+15550101000` Email address. Example: `john.doe@example.com` Your stable user reference for this person, such as your internal user ID. Didit uses it to link standalone checks to the same end user and reduce duplicate-detection noise. Example: `user-1234` ## Input rules & validation notes * For address services, send structured address fields instead of a single `address` string when possible. * `address.street_1` is the street address, including street number and street type. * `address.street_2` is apartment, unit, building, floor, or extra address line. Send it only when you have it. * `address.city` is city, suburb, district, locality, or neighborhood. * `address.region` is state, province, region, or town. * `address.postal_code` is postcode or postal code. * Address-based database services require at least street address and postal code; requests rejected before source lookup are not charged. ## How to call it ```bash cURL theme={null} curl -X POST "https://verification.didit.me/v3/database-validation/" \ -H "x-api-key: YOUR_API_KEY" \ -F "issuing_state=AUS" \ -F "services=aus_credit_bureau" \ -F "vendor_data=user-1234" \ -F "consent=true" \ -F "first_name=John" \ -F "last_name=Doe" \ -F "date_of_birth=1990-01-01" \ -F 'address={"street_1":"123 Sample Street","street_2":"Unit 4","city":"Sample City","region":"Sample State","postal_code":"10001","country":"US"}' ``` Every successful call returns HTTP `200`. The **`outcome_code`** field tells you what actually happened — distinguishing, for example, a real biometric mismatch (`BIOMETRIC_NO_MATCH`) from a selfie that could not be read (`BIOMETRIC_IMAGE_UNUSABLE`). The `status` shown is the default feature status; your configured [Partial Match / No Match actions](/core-technology/database-validation/database-validation-warnings) can override it. **`MATCH`** — The registry confirmed the identity and every checked field matched. ```json 200 OK — MATCH theme={null} { "request_id": "req_01H…", "status": "Approved", "issuing_state": "AUS", "match_type": "full_match", "validations": [ { "outcome_code": "MATCH", "service_id": "aus_credit_bureau", "service_name": "Australia Credit Bureau", "source_data": { "address": "123 Sample Street", "address_match_score": "1.000", "city": "Sample City", "date_of_birth": "1990-01-01", "first_name": "John", "full_name": "John Doe", "last_name": "Doe", "name_match_score": "1.000", "postal_code": "10001", "state": "Sample State", "street": "sample_value" }, "validation": { "address": "full_match", "date_of_birth": "full_match", "full_name": "full_match" } } ] } ``` **`PARTIAL_MATCH`** — The identification number was found but one or more personal fields (usually name or date of birth) did not fully match. ```json 200 OK — PARTIAL_MATCH theme={null} { "request_id": "req_01H…", "status": "In Review", "issuing_state": "AUS", "match_type": "partial_match", "validations": [ { "outcome_code": "PARTIAL_MATCH", "service_id": "aus_credit_bureau", "service_name": "Australia Credit Bureau", "source_data": { "address": "123 Sample Street", "address_match_score": "1.000", "city": "Sample City", "date_of_birth": "1990-01-01", "first_name": "John", "full_name": "John Doe", "last_name": "Doe", "name_match_score": "1.000", "postal_code": "10001", "state": "Sample State", "street": "sample_value" }, "validation": { "address": "full_match", "date_of_birth": "full_match", "full_name": "no_match" } } ] } ``` **`NO_MATCH`** — The registry returned no match for the submitted data. ```json 200 OK — NO_MATCH theme={null} { "request_id": "req_01H…", "status": "Declined", "issuing_state": "AUS", "match_type": "no_match", "validations": [ { "outcome_code": "NO_MATCH", "service_id": "aus_credit_bureau", "service_name": "Australia Credit Bureau", "source_data": { "address": "NO_MATCH", "date_of_birth": "NO_MATCH", "full_name": "NO_MATCH" }, "validation": { "address": "no_match", "date_of_birth": "no_match", "full_name": "no_match" } } ] } ``` ## Returned data The exact fields surfaced in `source_data` depend on what the registry returns. The generated example for `aus_credit_bureau` currently documents this normalized shape: * `address` * `address_match_score` * `city` * `date_of_birth` * `first_name` * `full_name` * `last_name` * `name_match_score` * `postal_code` * `state` * `street` ## Pricing & SLAs Australia Credit Bureau queries are billed only when Didit receives a conclusive result from the validation source. * **Per-call price:** \$0.70 USD. * **Billing:** per successful query. You are not charged when the registry is unreachable, when required fields are missing, or when the request is rejected before reaching the source. * **Latency:** typical p95 \< 2 s. * **Availability:** 99.9% per quarter on Didit's side; downstream source availability varies by country and dataset. ## Continue reading * [Australia Database Validation overview](/api-reference/database-validation/australia) * [Database Validation overview](/core-technology/database-validation/overview) * [Outcome Codes](/core-technology/database-validation/database-validation-outcome-codes) # Australia Death Check (BDM) Source: https://docs.didit.me/api-reference/database-validation/australia/death-check POST /v3/database-validation/ The official Australian Birth, Deaths, Marriages Register. Authoritative real-time identity lookup for Australia. Real-time lookup, pay-per-call.
The official Australian Birth, Deaths, Marriages Register. Didit exposes this service through `POST /v3/database-validation/` so you can verify the submitted data against the authoritative source and receive normalized match results. ## Coverage * **Coverage:** 100%\* * **Country:** Australia * **Service ID:** `aus_death_check` * **Data domain:** Other * **Category:** DeathRecord ## Inputs | Field | Required | Example | | --------------- | -------: | ------------ | | `first_name` | Yes | `John` | | `last_name` | Yes | `Doe` | | `date_of_birth` | Yes | `1990-01-01` | | `vendor_data` | No | `user-1234` | * **Required inputs:** `first_name`, `last_name`, `date_of_birth` * **Optional inputs:** `vendor_data` * **Consent:** Not required * **Workflow availability:** Available in workflow * **Coverage:** 100%\* * **Price:** \$0.05 per successful query ## Body parameters ISO 3166-1 alpha-3 country code for this database service. Example: `AUS` Array containing this service ID. Pinning the service keeps the request scoped to this exact database. Example: `aus_death_check` Given name to validate. Example: `John` Family name to validate. Example: `Doe` Date of birth in `YYYY-MM-DD` format. Example: `1990-01-01` Your stable user reference for this person, such as your internal user ID. Didit uses it to link standalone checks to the same end user and reduce duplicate-detection noise. Example: `user-1234` ## Input rules & validation notes * Send the fields listed above exactly as captured from the user or document. * Didit validates required fields before calling the database. Requests rejected before source lookup are not charged. ## How to call it ```bash cURL theme={null} curl -X POST "https://verification.didit.me/v3/database-validation/" \ -H "x-api-key: YOUR_API_KEY" \ -F "issuing_state=AUS" \ -F "services=aus_death_check" \ -F "vendor_data=user-1234" \ -F "first_name=John" \ -F "last_name=Doe" \ -F "date_of_birth=1990-01-01" ``` Every successful call returns HTTP `200`. The **`outcome_code`** field tells you what actually happened — distinguishing, for example, a real biometric mismatch (`BIOMETRIC_NO_MATCH`) from a selfie that could not be read (`BIOMETRIC_IMAGE_UNUSABLE`). The `status` shown is the default feature status; your configured [Partial Match / No Match actions](/core-technology/database-validation/database-validation-warnings) can override it. **`MATCH`** — The registry confirmed the identity and every checked field matched. ```json 200 OK — MATCH theme={null} { "request_id": "req_01H…", "status": "Approved", "issuing_state": "AUS", "match_type": "full_match", "validations": [ { "outcome_code": "MATCH", "service_id": "aus_death_check", "service_name": "Australia Death Check (BDM)", "source_data": { "date_of_birth": "1990-01-01", "first_name": "John", "full_name": "John Doe", "last_name": "Doe", "name_match_score": "1.000", "verifications": { "date_of_birth": true, "full_name": true } }, "validation": { "date_of_birth": "full_match", "full_name": "full_match" } } ] } ``` **`PARTIAL_MATCH`** — The identification number was found but one or more personal fields (usually name or date of birth) did not fully match. ```json 200 OK — PARTIAL_MATCH theme={null} { "request_id": "req_01H…", "status": "In Review", "issuing_state": "AUS", "match_type": "partial_match", "validations": [ { "outcome_code": "PARTIAL_MATCH", "service_id": "aus_death_check", "service_name": "Australia Death Check (BDM)", "source_data": { "date_of_birth": "1990-01-01", "first_name": "John", "full_name": "John Doe", "last_name": "Doe", "name_match_score": "1.000", "verifications": { "date_of_birth": true, "full_name": false } }, "validation": { "date_of_birth": "full_match", "full_name": "no_match" } } ] } ``` **`NO_MATCH`** — The registry returned no match for the submitted data. ```json 200 OK — NO_MATCH theme={null} { "request_id": "req_01H…", "status": "Declined", "issuing_state": "AUS", "match_type": "no_match", "validations": [ { "outcome_code": "NO_MATCH", "service_id": "aus_death_check", "service_name": "Australia Death Check (BDM)", "source_data": { "date_of_birth": "NO_MATCH", "full_name": "NO_MATCH" }, "validation": { "date_of_birth": "no_match", "full_name": "no_match" } } ] } ``` ## Returned data The exact fields surfaced in `source_data` depend on what the registry returns. The generated example for `aus_death_check` currently documents this normalized shape: * `date_of_birth` * `first_name` * `full_name` * `last_name` * `name_match_score` ## Pricing & SLAs Australia Death Check (BDM) queries are billed only when Didit receives a conclusive result from the validation source. * **Per-call price:** \$0.05 USD. * **Billing:** per successful query. You are not charged when the registry is unreachable, when required fields are missing, or when the request is rejected before reaching the source. * **Latency:** typical p95 \< 2 s. * **Availability:** 99.9% per quarter on Didit's side; downstream source availability varies by country and dataset. ## Continue reading * [Australia Database Validation overview](/api-reference/database-validation/australia) * [Database Validation overview](/core-technology/database-validation/overview) * [Outcome Codes](/core-technology/database-validation/database-validation-outcome-codes) # DVS - Australia Driver Licence Source: https://docs.didit.me/api-reference/database-validation/australia/driver-licence POST /v3/database-validation/ Verifies input data against the Document Verification Service (DVS). Authoritative real-time identity lookup for Australia. Real-time lookup, pay-per-call.
Verifies input data against the Document Verification Service (DVS). Didit exposes this service through `POST /v3/database-validation/` so you can verify the submitted data against the authoritative source and receive normalized match results. ## Coverage * **Coverage:** 100%\* * **Country:** Australia * **Service ID:** `aus_australia_driver_licence` * **Data domain:** Document * **Category:** DriverLicence ## Inputs | Field | Required | Example | | ---------------------------- | -------: | ----------------- | | `first_name` | Yes | `John` | | `last_name` | Yes | `Doe` | | `date_of_birth` | Yes | `1990-01-01` | | `driver_license_number` | Yes | `SAMPLE-DL-12345` | | `driver_license_card_number` | Yes | `87654321` | | `driver_license_state` | Yes | `Sample State` | | `middle_name` | No | `Demo` | | `vendor_data` | No | `user-1234` | * **Required inputs:** `first_name`, `last_name`, `date_of_birth`, `driver_license_number`, `driver_license_card_number`, `driver_license_state` * **Optional inputs:** `middle_name`, `vendor_data` * **Consent:** Required * **Workflow availability:** Available in workflow * **Coverage:** 100%\* * **Price:** \$0.45 per successful query ## Body parameters ISO 3166-1 alpha-3 country code for this database service. Example: `AUS` Array containing this service ID. Pinning the service keeps the request scoped to this exact database. Example: `aus_australia_driver_licence` Explicit end-user consent for this service. Example: `true` Given name to validate. Example: `John` Family name to validate. Example: `Doe` Date of birth in `YYYY-MM-DD` format. Example: `1990-01-01` Driver licence number. Example: `SAMPLE-DL-12345` `driver_license_card_number` value required by this database service. Example: `87654321` State or region that issued the driver licence. Example: `Sample State` Middle name, when available. Example: `Demo` Your stable user reference for this person, such as your internal user ID. Didit uses it to link standalone checks to the same end user and reduce duplicate-detection noise. Example: `user-1234` ## Input rules & validation notes * Send the fields listed above exactly as captured from the user or document. * Didit validates required fields before calling the database. Requests rejected before source lookup are not charged. ## How to call it ```bash cURL theme={null} curl -X POST "https://verification.didit.me/v3/database-validation/" \ -H "x-api-key: YOUR_API_KEY" \ -F "issuing_state=AUS" \ -F "services=aus_australia_driver_licence" \ -F "vendor_data=user-1234" \ -F "consent=true" \ -F "first_name=John" \ -F "last_name=Doe" \ -F "date_of_birth=1990-01-01" \ -F "driver_license_number=SAMPLE-DL-12345" \ -F "driver_license_card_number=87654321" \ -F "driver_license_state=Sample State" ``` Every successful call returns HTTP `200`. The **`outcome_code`** field tells you what actually happened — distinguishing, for example, a real biometric mismatch (`BIOMETRIC_NO_MATCH`) from a selfie that could not be read (`BIOMETRIC_IMAGE_UNUSABLE`). The `status` shown is the default feature status; your configured [Partial Match / No Match actions](/core-technology/database-validation/database-validation-warnings) can override it. **`MATCH`** — The registry confirmed the identity and every checked field matched. ```json 200 OK — MATCH theme={null} { "request_id": "req_01H…", "status": "Approved", "issuing_state": "AUS", "match_type": "full_match", "validations": [ { "outcome_code": "MATCH", "service_id": "aus_australia_driver_licence", "service_name": "DVS - Australia Driver Licence", "source_data": { "date_of_birth": "1990-01-01", "first_name": "John", "full_name": "John Doe", "identification_number": "SAMPLE-ID-12345", "last_name": "Doe", "name_match_score": "1.000", "verifications": { "date_of_birth": true, "full_name": true, "identification_number": true } }, "validation": { "date_of_birth": "full_match", "full_name": "full_match", "identification_number": "full_match" } } ] } ``` **`PARTIAL_MATCH`** — The identification number was found but one or more personal fields (usually name or date of birth) did not fully match. ```json 200 OK — PARTIAL_MATCH theme={null} { "request_id": "req_01H…", "status": "In Review", "issuing_state": "AUS", "match_type": "partial_match", "validations": [ { "outcome_code": "PARTIAL_MATCH", "service_id": "aus_australia_driver_licence", "service_name": "DVS - Australia Driver Licence", "source_data": { "date_of_birth": "1990-01-01", "first_name": "John", "full_name": "John Doe", "identification_number": "SAMPLE-ID-12345", "last_name": "Doe", "name_match_score": "1.000", "verifications": { "date_of_birth": true, "full_name": false, "identification_number": true } }, "validation": { "date_of_birth": "full_match", "full_name": "no_match", "identification_number": "full_match" } } ] } ``` **`NO_MATCH`** — The registry returned no match for the submitted data. ```json 200 OK — NO_MATCH theme={null} { "request_id": "req_01H…", "status": "Declined", "issuing_state": "AUS", "match_type": "no_match", "validations": [ { "outcome_code": "NO_MATCH", "service_id": "aus_australia_driver_licence", "service_name": "DVS - Australia Driver Licence", "source_data": { "date_of_birth": "NO_MATCH", "full_name": "NO_MATCH", "identification_number": "NO_MATCH" }, "validation": { "date_of_birth": "no_match", "full_name": "no_match", "identification_number": "no_match" } } ] } ``` ## Returned data The exact fields surfaced in `source_data` depend on what the registry returns. The generated example for `aus_australia_driver_licence` currently documents this normalized shape: * `date_of_birth` * `first_name` * `full_name` * `identification_number` * `last_name` * `name_match_score` ## Pricing & SLAs DVS - Australia Driver Licence queries are billed only when Didit receives a conclusive result from the validation source. * **Per-call price:** \$0.45 USD. * **Billing:** per successful query. You are not charged when the registry is unreachable, when required fields are missing, or when the request is rejected before reaching the source. * **Latency:** typical p95 \< 2 s. * **Availability:** 99.9% per quarter on Didit's side; downstream source availability varies by country and dataset. ## Continue reading * [Australia Database Validation overview](/api-reference/database-validation/australia) * [Database Validation overview](/core-technology/database-validation/overview) * [Outcome Codes](/core-technology/database-validation/database-validation-outcome-codes) # Australia Electoral Roll Source: https://docs.didit.me/api-reference/database-validation/australia/electoral-roll POST /v3/database-validation/ The official Government Electoral Roll service. Authoritative real-time identity lookup for Australia. Real-time lookup, pay-per-call.
The official Government Electoral Roll service. Didit exposes this service through `POST /v3/database-validation/` so you can verify the submitted data against the authoritative source and receive normalized match results. ## Coverage * **Coverage:** 100%\* * **Country:** Australia * **Service ID:** `aus_electoral_roll` * **Data domain:** Government * **Category:** ElectoralRoll ## Inputs | Field | Required | Example | | --------------------- | -------: | ------------------- | | `first_name` | Yes | `John` | | `last_name` | Yes | `Doe` | | `date_of_birth` | Yes | `1990-01-01` | | `address.street_1` | Yes | `123 Sample Street` | | `address.postal_code` | Yes | `10001` | | `address.street_2` | No | `Unit 4` | | `address.city` | No | `Sample City` | | `address.region` | No | `Sample State` | | `vendor_data` | No | `user-1234` | * **Required inputs:** `first_name`, `last_name`, `date_of_birth`, `address.street_1`, `address.postal_code` * **Optional inputs:** `address.street_2`, `address.city`, `address.region`, `vendor_data` * **Consent:** Required * **Workflow availability:** Available in workflow * **Coverage:** 100%\* * **Price:** \$0.45 per successful query ## Body parameters ISO 3166-1 alpha-3 country code for this database service. Example: `AUS` Array containing this service ID. Pinning the service keeps the request scoped to this exact database. Example: `aus_electoral_roll` Explicit end-user consent for this service. Example: `true` Given name to validate. Example: `John` Family name to validate. Example: `Doe` Date of birth in `YYYY-MM-DD` format. Example: `1990-01-01` Structured residential address object. Use `street_1`, `street_2`, `city`, `region`, `postal_code`, and `country`. A complete legacy address string is still accepted but not recommended. Example: `{"street_1":"123 Sample Street","street_2":"Unit 4","city":"Sample City","region":"Sample State","postal_code":"10001","country":"US"}` Your stable user reference for this person, such as your internal user ID. Didit uses it to link standalone checks to the same end user and reduce duplicate-detection noise. Example: `user-1234` ## Input rules & validation notes * For address services, send structured address fields instead of a single `address` string when possible. * `address.street_1` is the street address, including street number and street type. * `address.street_2` is apartment, unit, building, floor, or extra address line. Send it only when you have it. * `address.city` is city, suburb, district, locality, or neighborhood. * `address.region` is state, province, region, or town. * `address.postal_code` is postcode or postal code. * Address-based database services require at least street address and postal code; requests rejected before source lookup are not charged. ## How to call it ```bash cURL theme={null} curl -X POST "https://verification.didit.me/v3/database-validation/" \ -H "x-api-key: YOUR_API_KEY" \ -F "issuing_state=AUS" \ -F "services=aus_electoral_roll" \ -F "vendor_data=user-1234" \ -F "consent=true" \ -F "first_name=John" \ -F "last_name=Doe" \ -F "date_of_birth=1990-01-01" \ -F 'address={"street_1":"123 Sample Street","street_2":"Unit 4","city":"Sample City","region":"Sample State","postal_code":"10001","country":"US"}' ``` Every successful call returns HTTP `200`. The **`outcome_code`** field tells you what actually happened — distinguishing, for example, a real biometric mismatch (`BIOMETRIC_NO_MATCH`) from a selfie that could not be read (`BIOMETRIC_IMAGE_UNUSABLE`). The `status` shown is the default feature status; your configured [Partial Match / No Match actions](/core-technology/database-validation/database-validation-warnings) can override it. **`MATCH`** — The registry confirmed the identity and every checked field matched. ```json 200 OK — MATCH theme={null} { "request_id": "req_01H…", "status": "Approved", "issuing_state": "AUS", "match_type": "full_match", "validations": [ { "outcome_code": "MATCH", "service_id": "aus_electoral_roll", "service_name": "Australia Electoral Roll", "source_data": { "address": "123 Sample Street", "address_match_score": "1.000", "city": "Sample City", "date_of_birth": "1990-01-01", "first_name": "John", "full_name": "John Doe", "last_name": "Doe", "name_match_score": "1.000", "postal_code": "10001", "state": "Sample State", "street": "sample_value" }, "validation": { "address": "full_match", "date_of_birth": "full_match", "full_name": "full_match" } } ] } ``` **`PARTIAL_MATCH`** — The identification number was found but one or more personal fields (usually name or date of birth) did not fully match. ```json 200 OK — PARTIAL_MATCH theme={null} { "request_id": "req_01H…", "status": "In Review", "issuing_state": "AUS", "match_type": "partial_match", "validations": [ { "outcome_code": "PARTIAL_MATCH", "service_id": "aus_electoral_roll", "service_name": "Australia Electoral Roll", "source_data": { "address": "123 Sample Street", "address_match_score": "1.000", "city": "Sample City", "date_of_birth": "1990-01-01", "first_name": "John", "full_name": "John Doe", "last_name": "Doe", "name_match_score": "1.000", "postal_code": "10001", "state": "Sample State", "street": "sample_value" }, "validation": { "address": "full_match", "date_of_birth": "full_match", "full_name": "no_match" } } ] } ``` **`NO_MATCH`** — The registry returned no match for the submitted data. ```json 200 OK — NO_MATCH theme={null} { "request_id": "req_01H…", "status": "Declined", "issuing_state": "AUS", "match_type": "no_match", "validations": [ { "outcome_code": "NO_MATCH", "service_id": "aus_electoral_roll", "service_name": "Australia Electoral Roll", "source_data": { "address": "NO_MATCH", "date_of_birth": "NO_MATCH", "full_name": "NO_MATCH" }, "validation": { "address": "no_match", "date_of_birth": "no_match", "full_name": "no_match" } } ] } ``` ## Returned data The exact fields surfaced in `source_data` depend on what the registry returns. The generated example for `aus_electoral_roll` currently documents this normalized shape: * `address` * `address_match_score` * `city` * `date_of_birth` * `first_name` * `full_name` * `last_name` * `name_match_score` * `postal_code` * `state` * `street` ## Pricing & SLAs Australia Electoral Roll queries are billed only when Didit receives a conclusive result from the validation source. * **Per-call price:** \$0.45 USD. * **Billing:** per successful query. You are not charged when the registry is unreachable, when required fields are missing, or when the request is rejected before reaching the source. * **Latency:** typical p95 \< 2 s. * **Availability:** 99.9% per quarter on Didit's side; downstream source availability varies by country and dataset. ## Continue reading * [Australia Database Validation overview](/api-reference/database-validation/australia) * [Database Validation overview](/core-technology/database-validation/overview) * [Outcome Codes](/core-technology/database-validation/database-validation-outcome-codes) # Australia - DVS - ImmiCard Source: https://docs.didit.me/api-reference/database-validation/australia/immicard POST /v3/database-validation/ Verifies input data against the Document Verification Service (DVS). Authoritative real-time identity lookup for Australia. Real-time lookup, pay-per-call.
Verifies input data against the Document Verification Service (DVS). Didit exposes this service through `POST /v3/database-validation/` so you can verify the submitted data against the authoritative source and receive normalized match results. ## Coverage * **Coverage:** 100%\* * **Country:** Australia * **Service ID:** `aus_immicard` * **Data domain:** Document * **Category:** Visa ## Inputs | Field | Required | Example | | ----------------------- | -------: | ------------------- | | `first_name` | Yes | `John` | | `last_name` | Yes | `Doe` | | `date_of_birth` | Yes | `1990-01-01` | | `immi_card_number` | Yes | `SAMPLE-IMMI-12345` | | `immi_card_expiry_date` | Yes | `2030-01-01` | | `vendor_data` | No | `user-1234` | * **Required inputs:** `first_name`, `last_name`, `date_of_birth`, `immi_card_number`, `immi_card_expiry_date` * **Optional inputs:** `vendor_data` * **Consent:** Required * **Workflow availability:** Available in workflow * **Coverage:** 100%\* * **Price:** \$0.45 per successful query ## Body parameters ISO 3166-1 alpha-3 country code for this database service. Example: `AUS` Array containing this service ID. Pinning the service keeps the request scoped to this exact database. Example: `aus_immicard` Explicit end-user consent for this service. Example: `true` Given name to validate. Example: `John` Family name to validate. Example: `Doe` Date of birth in `YYYY-MM-DD` format. Example: `1990-01-01` `immi_card_number` value required by this database service. Example: `SAMPLE-IMMI-12345` `immi_card_expiry_date` value required by this database service. Example: `2030-01-01` Your stable user reference for this person, such as your internal user ID. Didit uses it to link standalone checks to the same end user and reduce duplicate-detection noise. Example: `user-1234` ## Input rules & validation notes * Send the fields listed above exactly as captured from the user or document. * Didit validates required fields before calling the database. Requests rejected before source lookup are not charged. ## How to call it ```bash cURL theme={null} curl -X POST "https://verification.didit.me/v3/database-validation/" \ -H "x-api-key: YOUR_API_KEY" \ -F "issuing_state=AUS" \ -F "services=aus_immicard" \ -F "vendor_data=user-1234" \ -F "consent=true" \ -F "first_name=John" \ -F "last_name=Doe" \ -F "date_of_birth=1990-01-01" \ -F "immi_card_number=SAMPLE-IMMI-12345" \ -F "immi_card_expiry_date=2030-01-01" ``` Every successful call returns HTTP `200`. The **`outcome_code`** field tells you what actually happened — distinguishing, for example, a real biometric mismatch (`BIOMETRIC_NO_MATCH`) from a selfie that could not be read (`BIOMETRIC_IMAGE_UNUSABLE`). The `status` shown is the default feature status; your configured [Partial Match / No Match actions](/core-technology/database-validation/database-validation-warnings) can override it. **`MATCH`** — The registry confirmed the identity and every checked field matched. ```json 200 OK — MATCH theme={null} { "request_id": "req_01H…", "status": "Approved", "issuing_state": "AUS", "match_type": "full_match", "validations": [ { "outcome_code": "MATCH", "service_id": "aus_immicard", "service_name": "Australia - DVS - ImmiCard", "source_data": { "date_of_birth": "1990-01-01", "first_name": "John", "identification_number": "SAMPLE-ID-12345", "last_name": "Doe" }, "validation": { "date_of_birth": "full_match", "full_name": "full_match", "identification_number": "full_match" } } ] } ``` **`PARTIAL_MATCH`** — The identification number was found but one or more personal fields (usually name or date of birth) did not fully match. ```json 200 OK — PARTIAL_MATCH theme={null} { "request_id": "req_01H…", "status": "In Review", "issuing_state": "AUS", "match_type": "partial_match", "validations": [ { "outcome_code": "PARTIAL_MATCH", "service_id": "aus_immicard", "service_name": "Australia - DVS - ImmiCard", "source_data": { "date_of_birth": "1990-01-01", "first_name": "John", "identification_number": "SAMPLE-ID-12345", "last_name": "Doe" }, "validation": { "date_of_birth": "full_match", "full_name": "no_match", "identification_number": "full_match" } } ] } ``` **`NO_MATCH`** — The registry returned no match for the submitted data. ```json 200 OK — NO_MATCH theme={null} { "request_id": "req_01H…", "status": "Declined", "issuing_state": "AUS", "match_type": "no_match", "validations": [ { "outcome_code": "NO_MATCH", "service_id": "aus_immicard", "service_name": "Australia - DVS - ImmiCard", "source_data": { "date_of_birth": "NO_MATCH", "full_name": "NO_MATCH", "identification_number": "NO_MATCH" }, "validation": { "date_of_birth": "no_match", "full_name": "no_match", "identification_number": "no_match" } } ] } ``` ## Returned data The exact fields surfaced in `source_data` depend on what the registry returns. The generated example for `aus_immicard` currently documents this normalized shape: * `date_of_birth` * `first_name` * `identification_number` * `last_name` ## Pricing & SLAs Australia - DVS - ImmiCard queries are billed only when Didit receives a conclusive result from the validation source. * **Per-call price:** \$0.45 USD. * **Billing:** per successful query. You are not charged when the registry is unreachable, when required fields are missing, or when the request is rejected before reaching the source. * **Latency:** typical p95 \< 2 s. * **Availability:** 99.9% per quarter on Didit's side; downstream source availability varies by country and dataset. ## Continue reading * [Australia Database Validation overview](/api-reference/database-validation/australia) * [Database Validation overview](/core-technology/database-validation/overview) * [Outcome Codes](/core-technology/database-validation/database-validation-outcome-codes) # Australia - DVS – Marriage Certificate Source: https://docs.didit.me/api-reference/database-validation/australia/marriage-certificate POST /v3/database-validation/ Verifies input data against the Document Verification Service (DVS). Authoritative real-time identity lookup for Australia. Real-time lookup, pay-per-call.
Verifies input data against the Document Verification Service (DVS). Didit exposes this service through `POST /v3/database-validation/` so you can verify the submitted data against the authoritative source and receive normalized match results. ## Coverage * **Coverage:** 100%\* * **Country:** Australia * **Service ID:** `aus_marriage_certificate` * **Data domain:** Identity * **Category:** CivilRegistry ## Inputs | Field | Required | Example | | ----------------------------- | -------: | ----------------------- | | `first_name` | Yes | `John` | | `last_name` | Yes | `Doe` | | `first_partner_name` | Yes | `Jamie` | | `last_partner_name` | Yes | `Example` | | `marriage_certificate_number` | Yes | `SAMPLE-MARRIAGE-12345` | | `birth_registration_number` | Yes | `SAMPLE-BIRTH-12345` | | `birth_registration_state` | Yes | `Sample State` | | `birth_registration_date` | Yes | `1990-01-01` | | `vendor_data` | No | `user-1234` | * **Required inputs:** `first_name`, `last_name`, `first_partner_name`, `last_partner_name`, `marriage_certificate_number`, `birth_registration_number`, `birth_registration_state`, `birth_registration_date` * **Optional inputs:** `vendor_data` * **Consent:** Required * **Workflow availability:** Available in workflow with field mapping * **Coverage:** 100%\* * **Price:** \$0.45 per successful query In a workflow, `first_partner_name`, `last_partner_name`, `birth_registration_state` and `birth_registration_date` are not printed on an identity document, so no step produces them on their own. Collect them from a Questionnaire answer, a Document AI extraction field, or a value you send when you create the session, and map each one on the Database Validation step. Until they are mapped the workflow editor shows this service disabled and names the missing input; at run time a missing input means the check is skipped before any query, so you are never billed for a database that could not be asked. ## Body parameters ISO 3166-1 alpha-3 country code for this database service. Example: `AUS` Array containing this service ID. Pinning the service keeps the request scoped to this exact database. Example: `aus_marriage_certificate` Explicit end-user consent for this service. Example: `true` Given name to validate. Example: `John` Family name to validate. Example: `Doe` `first_partner_name` value required by this database service. Example: `Jamie` `last_partner_name` value required by this database service. Example: `Example` `marriage_certificate_number` value required by this database service. Example: `SAMPLE-MARRIAGE-12345` `birth_registration_number` value required by this database service. Example: `SAMPLE-BIRTH-12345` `birth_registration_state` value required by this database service. Example: `Sample State` `birth_registration_date` value required by this database service. Example: `1990-01-01` Your stable user reference for this person, such as your internal user ID. Didit uses it to link standalone checks to the same end user and reduce duplicate-detection noise. Example: `user-1234` ## Input rules & validation notes * Send the fields listed above exactly as captured from the user or document. * Didit validates required fields before calling the database. Requests rejected before source lookup are not charged. ## How to call it ```bash cURL theme={null} curl -X POST "https://verification.didit.me/v3/database-validation/" \ -H "x-api-key: YOUR_API_KEY" \ -F "issuing_state=AUS" \ -F "services=aus_marriage_certificate" \ -F "vendor_data=user-1234" \ -F "consent=true" \ -F "first_name=John" \ -F "last_name=Doe" \ -F "first_partner_name=Jamie" \ -F "last_partner_name=Example" \ -F "marriage_certificate_number=SAMPLE-MARRIAGE-12345" \ -F "birth_registration_number=SAMPLE-BIRTH-12345" \ -F "birth_registration_state=Sample State" \ -F "birth_registration_date=1990-01-01" ``` Every successful call returns HTTP `200`. The **`outcome_code`** field tells you what actually happened — distinguishing, for example, a real biometric mismatch (`BIOMETRIC_NO_MATCH`) from a selfie that could not be read (`BIOMETRIC_IMAGE_UNUSABLE`). The `status` shown is the default feature status; your configured [Partial Match / No Match actions](/core-technology/database-validation/database-validation-warnings) can override it. **`MATCH`** — The registry confirmed the identity and every checked field matched. ```json 200 OK — MATCH theme={null} { "request_id": "req_01H…", "status": "Approved", "issuing_state": "AUS", "match_type": "full_match", "validations": [ { "outcome_code": "MATCH", "service_id": "aus_marriage_certificate", "service_name": "Australia - DVS – Marriage Certificate", "source_data": { "first_name": "John", "identification_number": "SAMPLE-ID-12345", "last_name": "Doe" }, "validation": { "full_name": "full_match", "identification_number": "full_match" } } ] } ``` **`PARTIAL_MATCH`** — The identification number was found but one or more personal fields (usually name or date of birth) did not fully match. ```json 200 OK — PARTIAL_MATCH theme={null} { "request_id": "req_01H…", "status": "In Review", "issuing_state": "AUS", "match_type": "partial_match", "validations": [ { "outcome_code": "PARTIAL_MATCH", "service_id": "aus_marriage_certificate", "service_name": "Australia - DVS – Marriage Certificate", "source_data": { "first_name": "John", "identification_number": "SAMPLE-ID-12345", "last_name": "Doe" }, "validation": { "full_name": "no_match", "identification_number": "full_match" } } ] } ``` **`NO_MATCH`** — The registry returned no match for the submitted data. ```json 200 OK — NO_MATCH theme={null} { "request_id": "req_01H…", "status": "Declined", "issuing_state": "AUS", "match_type": "no_match", "validations": [ { "outcome_code": "NO_MATCH", "service_id": "aus_marriage_certificate", "service_name": "Australia - DVS – Marriage Certificate", "source_data": { "full_name": "NO_MATCH", "identification_number": "NO_MATCH" }, "validation": { "full_name": "no_match", "identification_number": "no_match" } } ] } ``` ## Returned data The exact fields surfaced in `source_data` depend on what the registry returns. The generated example for `aus_marriage_certificate` currently documents this normalized shape: * `first_name` * `identification_number` * `last_name` ## Pricing & SLAs Australia - DVS – Marriage Certificate queries are billed only when Didit receives a conclusive result from the validation source. * **Per-call price:** \$0.45 USD. * **Billing:** per successful query. You are not charged when the registry is unreachable, when required fields are missing, or when the request is rejected before reaching the source. * **Latency:** typical p95 \< 2 s. * **Availability:** 99.9% per quarter on Didit's side; downstream source availability varies by country and dataset. ## Continue reading * [Australia Database Validation overview](/api-reference/database-validation/australia) * [Database Validation overview](/core-technology/database-validation/overview) * [Outcome Codes](/core-technology/database-validation/database-validation-outcome-codes) # DVS - Australia Medicare Card Source: https://docs.didit.me/api-reference/database-validation/australia/medicare-card POST /v3/database-validation/ Verifies input data against the Document Verification Service (DVS). Authoritative real-time identity lookup for Australia. Real-time lookup, pay-per-call.
Verifies input data against the Document Verification Service (DVS). Didit exposes this service through `POST /v3/database-validation/` so you can verify the submitted data against the authoritative source and receive normalized match results. ## Coverage * **Coverage:** 100%\* * **Country:** Australia * **Service ID:** `aus_australia_medicare_card` * **Data domain:** Health * **Category:** Healthcare ## Inputs | Field | Required | Example | | ---------------------- | -------: | ------------ | | `first_name` | Yes | `John` | | `last_name` | Yes | `Doe` | | `date_of_birth` | Yes | `1990-01-01` | | `medicare_card_number` | Yes | `1111111111` | | `middle_name` | No | `Demo` | | `vendor_data` | No | `user-1234` | * **Required inputs:** `first_name`, `last_name`, `date_of_birth`, `medicare_card_number` * **Optional inputs:** `middle_name`, `vendor_data` * **Consent:** Required * **Workflow availability:** Available in workflow * **Coverage:** 100%\* * **Price:** \$0.45 per successful query Not every document this service accepts carries the identifier it queries by. When the identifier is not extracted from the document the check is recorded as **not applicable** - no database is queried and you are not charged - which for some countries is a large share of real users. To cover them, also collect the identifier from a Questionnaire answer, a Document AI extraction field, or a value you send when you create the session, and map it on the Database Validation step. ## Body parameters ISO 3166-1 alpha-3 country code for this database service. Example: `AUS` Array containing this service ID. Pinning the service keeps the request scoped to this exact database. Example: `aus_australia_medicare_card` Explicit end-user consent for this service. Example: `true` Given name to validate. Example: `John` Family name to validate. Example: `Doe` Date of birth in `YYYY-MM-DD` format. Example: `1990-01-01` Medicare card number. Example: `1111111111` Middle name, when available. Example: `Demo` Your stable user reference for this person, such as your internal user ID. Didit uses it to link standalone checks to the same end user and reduce duplicate-detection noise. Example: `user-1234` ## Input rules & validation notes * Australian Medicare card number (exactly 10 digits) * `medicare_card_number` must contain digits only; remove spaces, hyphens, and punctuation before sending the request. * `medicare_card_number` must be exactly 10 characters long. ## How to call it ```bash cURL theme={null} curl -X POST "https://verification.didit.me/v3/database-validation/" \ -H "x-api-key: YOUR_API_KEY" \ -F "issuing_state=AUS" \ -F "services=aus_australia_medicare_card" \ -F "vendor_data=user-1234" \ -F "consent=true" \ -F "first_name=John" \ -F "last_name=Doe" \ -F "date_of_birth=1990-01-01" \ -F "medicare_card_number=1111111111" ``` Every successful call returns HTTP `200`. The **`outcome_code`** field tells you what actually happened — distinguishing, for example, a real biometric mismatch (`BIOMETRIC_NO_MATCH`) from a selfie that could not be read (`BIOMETRIC_IMAGE_UNUSABLE`). The `status` shown is the default feature status; your configured [Partial Match / No Match actions](/core-technology/database-validation/database-validation-warnings) can override it. **`MATCH`** — The registry confirmed the identity and every checked field matched. ```json 200 OK — MATCH theme={null} { "request_id": "req_01H…", "status": "Approved", "issuing_state": "AUS", "match_type": "full_match", "validations": [ { "outcome_code": "MATCH", "service_id": "aus_australia_medicare_card", "service_name": "DVS - Australia Medicare Card", "source_data": { "date_of_birth": "1990-01-01", "first_name": "John", "identification_number": "SAMPLE-ID-12345", "last_name": "Doe", "middle_name": "Demo" }, "validation": { "date_of_birth": "full_match", "full_name": "full_match", "identification_number": "full_match" } } ] } ``` **`PARTIAL_MATCH`** — The identification number was found but one or more personal fields (usually name or date of birth) did not fully match. ```json 200 OK — PARTIAL_MATCH theme={null} { "request_id": "req_01H…", "status": "In Review", "issuing_state": "AUS", "match_type": "partial_match", "validations": [ { "outcome_code": "PARTIAL_MATCH", "service_id": "aus_australia_medicare_card", "service_name": "DVS - Australia Medicare Card", "source_data": { "date_of_birth": "1990-01-01", "first_name": "John", "identification_number": "SAMPLE-ID-12345", "last_name": "Doe", "middle_name": "Demo" }, "validation": { "date_of_birth": "full_match", "full_name": "no_match", "identification_number": "full_match" } } ] } ``` **`NO_MATCH`** — The registry returned no match for the submitted data. ```json 200 OK — NO_MATCH theme={null} { "request_id": "req_01H…", "status": "Declined", "issuing_state": "AUS", "match_type": "no_match", "validations": [ { "outcome_code": "NO_MATCH", "service_id": "aus_australia_medicare_card", "service_name": "DVS - Australia Medicare Card", "source_data": { "date_of_birth": "NO_MATCH", "full_name": "NO_MATCH", "identification_number": "NO_MATCH" }, "validation": { "date_of_birth": "no_match", "full_name": "no_match", "identification_number": "no_match" } } ] } ``` ## Returned data The exact fields surfaced in `source_data` depend on what the registry returns. The generated example for `aus_australia_medicare_card` currently documents this normalized shape: * `date_of_birth` * `first_name` * `identification_number` * `last_name` * `middle_name` ## Pricing & SLAs DVS - Australia Medicare Card queries are billed only when Didit receives a conclusive result from the validation source. * **Per-call price:** \$0.45 USD. * **Billing:** per successful query. You are not charged when the registry is unreachable, when required fields are missing, or when the request is rejected before reaching the source. * **Latency:** typical p95 \< 2 s. * **Availability:** 99.9% per quarter on Didit's side; downstream source availability varies by country and dataset. ## Continue reading * [Australia Database Validation overview](/api-reference/database-validation/australia) * [Database Validation overview](/core-technology/database-validation/overview) * [Outcome Codes](/core-technology/database-validation/database-validation-outcome-codes) # DVS - Australia Passport Source: https://docs.didit.me/api-reference/database-validation/australia/passport POST /v3/database-validation/ Verifies input data against the Document Verification Service (DVS). Authoritative real-time identity lookup for Australia. Real-time lookup, pay-per-call.
Verifies input data against the Document Verification Service (DVS). Didit exposes this service through `POST /v3/database-validation/` so you can verify the submitted data against the authoritative source and receive normalized match results. ## Coverage * **Coverage:** 100%\* * **Country:** Australia * **Service ID:** `aus_australia_passport` * **Data domain:** Document * **Category:** Passport ## Inputs | Field | Required | Example | | ----------------- | -------: | ------------------- | | `first_name` | Yes | `John` | | `last_name` | Yes | `Doe` | | `date_of_birth` | Yes | `1990-01-01` | | `passport_number` | Yes | `SAMPLE-PASS-12345` | | `middle_name` | No | `Demo` | | `vendor_data` | No | `user-1234` | * **Required inputs:** `first_name`, `last_name`, `date_of_birth`, `passport_number` * **Optional inputs:** `middle_name`, `vendor_data` * **Consent:** Required * **Workflow availability:** Available in workflow * **Coverage:** 100%\* * **Price:** \$0.45 per successful query ## Body parameters ISO 3166-1 alpha-3 country code for this database service. Example: `AUS` Array containing this service ID. Pinning the service keeps the request scoped to this exact database. Example: `aus_australia_passport` Explicit end-user consent for this service. Example: `true` Given name to validate. Example: `John` Family name to validate. Example: `Doe` Date of birth in `YYYY-MM-DD` format. Example: `1990-01-01` Passport number. Example: `SAMPLE-PASS-12345` Middle name, when available. Example: `Demo` Your stable user reference for this person, such as your internal user ID. Didit uses it to link standalone checks to the same end user and reduce duplicate-detection noise. Example: `user-1234` ## Input rules & validation notes * Send the fields listed above exactly as captured from the user or document. * Didit validates required fields before calling the database. Requests rejected before source lookup are not charged. ## How to call it ```bash cURL theme={null} curl -X POST "https://verification.didit.me/v3/database-validation/" \ -H "x-api-key: YOUR_API_KEY" \ -F "issuing_state=AUS" \ -F "services=aus_australia_passport" \ -F "vendor_data=user-1234" \ -F "consent=true" \ -F "first_name=John" \ -F "last_name=Doe" \ -F "date_of_birth=1990-01-01" \ -F "passport_number=SAMPLE-PASS-12345" ``` Every successful call returns HTTP `200`. The **`outcome_code`** field tells you what actually happened — distinguishing, for example, a real biometric mismatch (`BIOMETRIC_NO_MATCH`) from a selfie that could not be read (`BIOMETRIC_IMAGE_UNUSABLE`). The `status` shown is the default feature status; your configured [Partial Match / No Match actions](/core-technology/database-validation/database-validation-warnings) can override it. **`MATCH`** — The registry confirmed the identity and every checked field matched. ```json 200 OK — MATCH theme={null} { "request_id": "req_01H…", "status": "Approved", "issuing_state": "AUS", "match_type": "full_match", "validations": [ { "outcome_code": "MATCH", "service_id": "aus_australia_passport", "service_name": "DVS - Australia Passport", "source_data": { "date_of_birth": "1990-01-01", "first_name": "John", "identification_number": "SAMPLE-ID-12345", "last_name": "Doe", "middle_name": "Demo" }, "validation": { "date_of_birth": "full_match", "full_name": "full_match", "identification_number": "full_match" } } ] } ``` **`PARTIAL_MATCH`** — The identification number was found but one or more personal fields (usually name or date of birth) did not fully match. ```json 200 OK — PARTIAL_MATCH theme={null} { "request_id": "req_01H…", "status": "In Review", "issuing_state": "AUS", "match_type": "partial_match", "validations": [ { "outcome_code": "PARTIAL_MATCH", "service_id": "aus_australia_passport", "service_name": "DVS - Australia Passport", "source_data": { "date_of_birth": "1990-01-01", "first_name": "John", "identification_number": "SAMPLE-ID-12345", "last_name": "Doe", "middle_name": "Demo" }, "validation": { "date_of_birth": "full_match", "full_name": "no_match", "identification_number": "full_match" } } ] } ``` **`NO_MATCH`** — The registry returned no match for the submitted data. ```json 200 OK — NO_MATCH theme={null} { "request_id": "req_01H…", "status": "Declined", "issuing_state": "AUS", "match_type": "no_match", "validations": [ { "outcome_code": "NO_MATCH", "service_id": "aus_australia_passport", "service_name": "DVS - Australia Passport", "source_data": { "date_of_birth": "NO_MATCH", "full_name": "NO_MATCH", "identification_number": "NO_MATCH" }, "validation": { "date_of_birth": "no_match", "full_name": "no_match", "identification_number": "no_match" } } ] } ``` ## Returned data The exact fields surfaced in `source_data` depend on what the registry returns. The generated example for `aus_australia_passport` currently documents this normalized shape: * `date_of_birth` * `first_name` * `identification_number` * `last_name` * `middle_name` ## Pricing & SLAs DVS - Australia Passport queries are billed only when Didit receives a conclusive result from the validation source. * **Per-call price:** \$0.45 USD. * **Billing:** per successful query. You are not charged when the registry is unreachable, when required fields are missing, or when the request is rejected before reaching the source. * **Latency:** typical p95 \< 2 s. * **Availability:** 99.9% per quarter on Didit's side; downstream source availability varies by country and dataset. ## Continue reading * [Australia Database Validation overview](/api-reference/database-validation/australia) * [Database Validation overview](/core-technology/database-validation/overview) * [Outcome Codes](/core-technology/database-validation/database-validation-outcome-codes) # Australia Superannuation & Payroll Source: https://docs.didit.me/api-reference/database-validation/australia/superannuation-payroll POST /v3/database-validation/ Verifies input data to an authorised Superannuation and Payroll administrator and services provider. Authoritative real-time identity lookup for Australia. Real-time lookup, pay-per-call.
Verifies input data to an authorised Superannuation and Payroll administrator and services provider. Didit exposes this service through `POST /v3/database-validation/` so you can verify the submitted data against the authoritative source and receive normalized match results. ## Coverage * **Coverage:** \~ 50% * **Country:** Australia * **Service ID:** `aus_superannuation_payroll` * **Data domain:** Financial * **Category:** Superannuation ## Inputs | Field | Required | Example | | --------------------- | -------: | ------------------- | | `first_name` | Yes | `John` | | `last_name` | Yes | `Doe` | | `date_of_birth` | Yes | `1990-01-01` | | `address.street_1` | No | `123 Sample Street` | | `address.street_2` | No | `Unit 4` | | `address.city` | No | `Sample City` | | `address.region` | No | `Sample State` | | `address.postal_code` | No | `10001` | | `vendor_data` | No | `user-1234` | * **Required inputs:** `first_name`, `last_name`, `date_of_birth` * **Optional inputs:** `address.street_1`, `address.street_2`, `address.city`, `address.region`, `address.postal_code`, `vendor_data` * **Consent:** Required * **Workflow availability:** Available in workflow * **Coverage:** \~ 50% * **Price:** \$0.67 per successful query ## Body parameters ISO 3166-1 alpha-3 country code for this database service. Example: `AUS` Array containing this service ID. Pinning the service keeps the request scoped to this exact database. Example: `aus_superannuation_payroll` Explicit end-user consent for this service. Example: `true` Given name to validate. Example: `John` Family name to validate. Example: `Doe` Date of birth in `YYYY-MM-DD` format. Example: `1990-01-01` Structured residential address object. Use `street_1`, `street_2`, `city`, `region`, `postal_code`, and `country`. A complete legacy address string is still accepted but not recommended. Example: `{"street_1":"123 Sample Street","street_2":"Unit 4","city":"Sample City","region":"Sample State","postal_code":"10001","country":"US"}` Your stable user reference for this person, such as your internal user ID. Didit uses it to link standalone checks to the same end user and reduce duplicate-detection noise. Example: `user-1234` ## Input rules & validation notes * `address` is optional for this service. You can send one complete `address` string and Didit will split it into structured address elements when possible, or you can send the structured fields explicitly. * For address services, send structured address fields instead of a single `address` string when possible. * `address.street_1` is the street address, including street number and street type. * `address.street_2` is apartment, unit, building, floor, or extra address line. Send it only when you have it. * `address.city` is city, suburb, district, locality, or neighborhood. * `address.region` is state, province, region, or town. * `address.postal_code` is postcode or postal code. * Address-based database services require at least street address and postal code; requests rejected before source lookup are not charged. ## How to call it ```bash cURL theme={null} curl -X POST "https://verification.didit.me/v3/database-validation/" \ -H "x-api-key: YOUR_API_KEY" \ -F "issuing_state=AUS" \ -F "services=aus_superannuation_payroll" \ -F "vendor_data=user-1234" \ -F "consent=true" \ -F "first_name=John" \ -F "last_name=Doe" \ -F "date_of_birth=1990-01-01" ``` Every successful call returns HTTP `200`. The **`outcome_code`** field tells you what actually happened — distinguishing, for example, a real biometric mismatch (`BIOMETRIC_NO_MATCH`) from a selfie that could not be read (`BIOMETRIC_IMAGE_UNUSABLE`). The `status` shown is the default feature status; your configured [Partial Match / No Match actions](/core-technology/database-validation/database-validation-warnings) can override it. **`MATCH`** — The registry confirmed the identity and every checked field matched. ```json 200 OK — MATCH theme={null} { "request_id": "req_01H…", "status": "Approved", "issuing_state": "AUS", "match_type": "full_match", "validations": [ { "outcome_code": "MATCH", "service_id": "aus_superannuation_payroll", "service_name": "Australia Superannuation & Payroll", "source_data": { "address": "123 Sample Street", "date_of_birth": "1990-01-01", "first_name": "John", "last_name": "Doe" }, "validation": { "date_of_birth": "full_match", "full_name": "full_match" } } ] } ``` **`PARTIAL_MATCH`** — The identification number was found but one or more personal fields (usually name or date of birth) did not fully match. ```json 200 OK — PARTIAL_MATCH theme={null} { "request_id": "req_01H…", "status": "In Review", "issuing_state": "AUS", "match_type": "partial_match", "validations": [ { "outcome_code": "PARTIAL_MATCH", "service_id": "aus_superannuation_payroll", "service_name": "Australia Superannuation & Payroll", "source_data": { "address": "123 Sample Street", "date_of_birth": "1990-01-01", "first_name": "John", "last_name": "Doe" }, "validation": { "date_of_birth": "full_match", "full_name": "no_match" } } ] } ``` **`NO_MATCH`** — The registry returned no match for the submitted data. ```json 200 OK — NO_MATCH theme={null} { "request_id": "req_01H…", "status": "Declined", "issuing_state": "AUS", "match_type": "no_match", "validations": [ { "outcome_code": "NO_MATCH", "service_id": "aus_superannuation_payroll", "service_name": "Australia Superannuation & Payroll", "source_data": { "date_of_birth": "NO_MATCH", "full_name": "NO_MATCH" }, "validation": { "date_of_birth": "no_match", "full_name": "no_match" } } ] } ``` ## Returned data The exact fields surfaced in `source_data` depend on what the registry returns. The generated example for `aus_superannuation_payroll` currently documents this normalized shape: * `address` * `date_of_birth` * `first_name` * `last_name` ## Pricing & SLAs Australia Superannuation & Payroll queries are billed only when Didit receives a conclusive result from the validation source. * **Per-call price:** \$0.67 USD. * **Billing:** per successful query. You are not charged when the registry is unreachable, when required fields are missing, or when the request is rejected before reaching the source. * **Latency:** typical p95 \< 2 s. * **Availability:** 99.9% per quarter on Didit's side; downstream source availability varies by country and dataset. ## Continue reading * [Australia Database Validation overview](/api-reference/database-validation/australia) * [Database Validation overview](/core-technology/database-validation/overview) * [Outcome Codes](/core-technology/database-validation/database-validation-outcome-codes) # Australia - DVS - Travel Document Source: https://docs.didit.me/api-reference/database-validation/australia/travel-document POST /v3/database-validation/ Verifies input data against the Document Verification Service (DVS). Authoritative real-time identity lookup for Australia. Real-time lookup, pay-per-call.
Verifies input data against the Document Verification Service (DVS). Didit exposes this service through `POST /v3/database-validation/` so you can verify the submitted data against the authoritative source and receive normalized match results. ## Coverage * **Coverage:** 100%\* * **Country:** Australia * **Service ID:** `aus_travel_document` * **Data domain:** Document * **Category:** Passport ## Inputs | Field | Required | Example | | ------------------------ | -------: | ------------------- | | `first_name` | Yes | `John` | | `last_name` | Yes | `Doe` | | `passport_number` | Yes | `SAMPLE-PASS-12345` | | `passport_issue_country` | Yes | `USA` | | `vendor_data` | No | `user-1234` | * **Required inputs:** `first_name`, `last_name`, `passport_number`, `passport_issue_country` * **Optional inputs:** `vendor_data` * **Consent:** Required * **Workflow availability:** Available in workflow * **Coverage:** 100%\* * **Price:** \$0.45 per successful query ## Body parameters ISO 3166-1 alpha-3 country code for this database service. Example: `AUS` Array containing this service ID. Pinning the service keeps the request scoped to this exact database. Example: `aus_travel_document` Explicit end-user consent for this service. Example: `true` Given name to validate. Example: `John` Family name to validate. Example: `Doe` Passport number. Example: `SAMPLE-PASS-12345` ISO 3166-1 alpha-3 country that issued the passport. Example: `USA` Your stable user reference for this person, such as your internal user ID. Didit uses it to link standalone checks to the same end user and reduce duplicate-detection noise. Example: `user-1234` ## Input rules & validation notes * ISO 3166-1 alpha-3 country code * `passport_issue_country` must use uppercase letters. * `passport_issue_country` must match `[A-Za-z]{3}`. ## How to call it ```bash cURL theme={null} curl -X POST "https://verification.didit.me/v3/database-validation/" \ -H "x-api-key: YOUR_API_KEY" \ -F "issuing_state=AUS" \ -F "services=aus_travel_document" \ -F "vendor_data=user-1234" \ -F "consent=true" \ -F "first_name=John" \ -F "last_name=Doe" \ -F "passport_number=SAMPLE-PASS-12345" \ -F "passport_issue_country=USA" ``` Every successful call returns HTTP `200`. The **`outcome_code`** field tells you what actually happened — distinguishing, for example, a real biometric mismatch (`BIOMETRIC_NO_MATCH`) from a selfie that could not be read (`BIOMETRIC_IMAGE_UNUSABLE`). The `status` shown is the default feature status; your configured [Partial Match / No Match actions](/core-technology/database-validation/database-validation-warnings) can override it. **`MATCH`** — The registry confirmed the identity and every checked field matched. ```json 200 OK — MATCH theme={null} { "request_id": "req_01H…", "status": "Approved", "issuing_state": "AUS", "match_type": "full_match", "validations": [ { "outcome_code": "MATCH", "service_id": "aus_travel_document", "service_name": "Australia - DVS - Travel Document", "source_data": { "first_name": "John", "identification_number": "SAMPLE-ID-12345", "last_name": "Doe" }, "validation": { "full_name": "full_match", "identification_number": "full_match" } } ] } ``` **`PARTIAL_MATCH`** — The identification number was found but one or more personal fields (usually name or date of birth) did not fully match. ```json 200 OK — PARTIAL_MATCH theme={null} { "request_id": "req_01H…", "status": "In Review", "issuing_state": "AUS", "match_type": "partial_match", "validations": [ { "outcome_code": "PARTIAL_MATCH", "service_id": "aus_travel_document", "service_name": "Australia - DVS - Travel Document", "source_data": { "first_name": "John", "identification_number": "SAMPLE-ID-12345", "last_name": "Doe" }, "validation": { "full_name": "no_match", "identification_number": "full_match" } } ] } ``` **`NO_MATCH`** — The registry returned no match for the submitted data. ```json 200 OK — NO_MATCH theme={null} { "request_id": "req_01H…", "status": "Declined", "issuing_state": "AUS", "match_type": "no_match", "validations": [ { "outcome_code": "NO_MATCH", "service_id": "aus_travel_document", "service_name": "Australia - DVS - Travel Document", "source_data": { "full_name": "NO_MATCH", "identification_number": "NO_MATCH" }, "validation": { "full_name": "no_match", "identification_number": "no_match" } } ] } ``` ## Returned data The exact fields surfaced in `source_data` depend on what the registry returns. The generated example for `aus_travel_document` currently documents this normalized shape: * `first_name` * `identification_number` * `last_name` ## Pricing & SLAs Australia - DVS - Travel Document queries are billed only when Didit receives a conclusive result from the validation source. * **Per-call price:** \$0.45 USD. * **Billing:** per successful query. You are not charged when the registry is unreachable, when required fields are missing, or when the request is rejected before reaching the source. * **Latency:** typical p95 \< 2 s. * **Availability:** 99.9% per quarter on Didit's side; downstream source availability varies by country and dataset. ## Continue reading * [Australia Database Validation overview](/api-reference/database-validation/australia) * [Database Validation overview](/core-technology/database-validation/overview) * [Outcome Codes](/core-technology/database-validation/database-validation-outcome-codes) # Australia VEVO Source: https://docs.didit.me/api-reference/database-validation/australia/vevo POST /v3/database-validation/ Verifies input data against the Department of Home Affairs Visa database. Authoritative real-time identity lookup for Australia. Real-time lookup, pay-per-call.
Verifies input data against the Department of Home Affairs Visa database. Didit exposes this service through `POST /v3/database-validation/` so you can verify the submitted data against the authoritative source and receive normalized match results. ## Coverage * **Coverage:** 100%\* * **Country:** Australia * **Service ID:** `aus_vevo` * **Data domain:** Document * **Category:** Visa ## Inputs | Field | Required | Example | | ------------------------ | -------: | ------------------- | | `first_name` | Yes | `John` | | `last_name` | Yes | `Doe` | | `date_of_birth` | Yes | `1990-01-01` | | `passport_number` | Yes | `SAMPLE-PASS-12345` | | `passport_issue_country` | Yes | `USA` | | `vendor_data` | No | `user-1234` | * **Required inputs:** `first_name`, `last_name`, `date_of_birth`, `passport_number`, `passport_issue_country` * **Optional inputs:** `vendor_data` * **Consent:** Required * **Workflow availability:** Available in workflow * **Coverage:** 100%\* * **Price:** \$0.32 per successful query ## Body parameters ISO 3166-1 alpha-3 country code for this database service. Example: `AUS` Array containing this service ID. Pinning the service keeps the request scoped to this exact database. Example: `aus_vevo` Explicit end-user consent for this service. Example: `true` Given name to validate. Example: `John` Family name to validate. Example: `Doe` Date of birth in `YYYY-MM-DD` format. Example: `1990-01-01` Passport number. Example: `SAMPLE-PASS-12345` ISO 3166-1 alpha-3 country that issued the passport. Example: `USA` Your stable user reference for this person, such as your internal user ID. Didit uses it to link standalone checks to the same end user and reduce duplicate-detection noise. Example: `user-1234` ## Input rules & validation notes * ISO 3166-1 alpha-3 country code * `passport_issue_country` must use uppercase letters. * `passport_issue_country` must match `[A-Za-z]{3}`. ## How to call it ```bash cURL theme={null} curl -X POST "https://verification.didit.me/v3/database-validation/" \ -H "x-api-key: YOUR_API_KEY" \ -F "issuing_state=AUS" \ -F "services=aus_vevo" \ -F "vendor_data=user-1234" \ -F "consent=true" \ -F "first_name=John" \ -F "last_name=Doe" \ -F "date_of_birth=1990-01-01" \ -F "passport_number=SAMPLE-PASS-12345" \ -F "passport_issue_country=USA" ``` Every successful call returns HTTP `200`. The **`outcome_code`** field tells you what actually happened — distinguishing, for example, a real biometric mismatch (`BIOMETRIC_NO_MATCH`) from a selfie that could not be read (`BIOMETRIC_IMAGE_UNUSABLE`). The `status` shown is the default feature status; your configured [Partial Match / No Match actions](/core-technology/database-validation/database-validation-warnings) can override it. **`MATCH`** — The registry confirmed the identity and every checked field matched. ```json 200 OK — MATCH theme={null} { "request_id": "req_01H…", "status": "Approved", "issuing_state": "AUS", "match_type": "full_match", "validations": [ { "outcome_code": "MATCH", "service_id": "aus_vevo", "service_name": "Australia VEVO", "source_data": { "date_of_birth": "1990-01-01", "identification_number": "SAMPLE-ID-12345", "name_match_score": "1.000", "verifications": { "date_of_birth": true, "full_name": true, "identification_number": true } }, "validation": { "date_of_birth": "full_match", "full_name": "full_match", "identification_number": "full_match" } } ] } ``` **`PARTIAL_MATCH`** — The identification number was found but one or more personal fields (usually name or date of birth) did not fully match. ```json 200 OK — PARTIAL_MATCH theme={null} { "request_id": "req_01H…", "status": "In Review", "issuing_state": "AUS", "match_type": "partial_match", "validations": [ { "outcome_code": "PARTIAL_MATCH", "service_id": "aus_vevo", "service_name": "Australia VEVO", "source_data": { "date_of_birth": "1990-01-01", "identification_number": "SAMPLE-ID-12345", "name_match_score": "1.000", "verifications": { "date_of_birth": true, "full_name": false, "identification_number": true } }, "validation": { "date_of_birth": "full_match", "full_name": "no_match", "identification_number": "full_match" } } ] } ``` **`NO_MATCH`** — The registry returned no match for the submitted data. ```json 200 OK — NO_MATCH theme={null} { "request_id": "req_01H…", "status": "Declined", "issuing_state": "AUS", "match_type": "no_match", "validations": [ { "outcome_code": "NO_MATCH", "service_id": "aus_vevo", "service_name": "Australia VEVO", "source_data": { "date_of_birth": "NO_MATCH", "full_name": "NO_MATCH", "identification_number": "NO_MATCH" }, "validation": { "date_of_birth": "no_match", "full_name": "no_match", "identification_number": "no_match" } } ] } ``` ## Returned data The exact fields surfaced in `source_data` depend on what the registry returns. The generated example for `aus_vevo` currently documents this normalized shape: * `date_of_birth` * `identification_number` * `name_match_score` ## Pricing & SLAs Australia VEVO queries are billed only when Didit receives a conclusive result from the validation source. * **Per-call price:** \$0.32 USD. * **Billing:** per successful query. You are not charged when the registry is unreachable, when required fields are missing, or when the request is rejected before reaching the source. * **Latency:** typical p95 \< 2 s. * **Availability:** 99.9% per quarter on Didit's side; downstream source availability varies by country and dataset. ## Continue reading * [Australia Database Validation overview](/api-reference/database-validation/australia) * [Database Validation overview](/core-technology/database-validation/overview) * [Outcome Codes](/core-technology/database-validation/database-validation-outcome-codes) # DVS - Australia Visa Source: https://docs.didit.me/api-reference/database-validation/australia/visa POST /v3/database-validation/ Verifies input data against the Document Verification Service (DVS). Authoritative real-time identity lookup for Australia. Real-time lookup, pay-per-call.
Verifies input data against the Document Verification Service (DVS). Didit exposes this service through `POST /v3/database-validation/` so you can verify the submitted data against the authoritative source and receive normalized match results. ## Coverage * **Coverage:** 100%\* * **Country:** Australia * **Service ID:** `aus_australia_visa` * **Data domain:** Document * **Category:** Visa ## Inputs | Field | Required | Example | | ----------------- | -------: | ------------------- | | `first_name` | Yes | `John` | | `last_name` | Yes | `Doe` | | `date_of_birth` | Yes | `1990-01-01` | | `passport_number` | Yes | `SAMPLE-PASS-12345` | | `vendor_data` | No | `user-1234` | * **Required inputs:** `first_name`, `last_name`, `date_of_birth`, `passport_number` * **Optional inputs:** `vendor_data` * **Consent:** Required * **Workflow availability:** Available in workflow * **Coverage:** 100%\* * **Price:** \$0.45 per successful query ## Body parameters ISO 3166-1 alpha-3 country code for this database service. Example: `AUS` Array containing this service ID. Pinning the service keeps the request scoped to this exact database. Example: `aus_australia_visa` Explicit end-user consent for this service. Example: `true` Given name to validate. Example: `John` Family name to validate. Example: `Doe` Date of birth in `YYYY-MM-DD` format. Example: `1990-01-01` Passport number. Example: `SAMPLE-PASS-12345` Your stable user reference for this person, such as your internal user ID. Didit uses it to link standalone checks to the same end user and reduce duplicate-detection noise. Example: `user-1234` ## Input rules & validation notes * Send the fields listed above exactly as captured from the user or document. * Didit validates required fields before calling the database. Requests rejected before source lookup are not charged. ## How to call it ```bash cURL theme={null} curl -X POST "https://verification.didit.me/v3/database-validation/" \ -H "x-api-key: YOUR_API_KEY" \ -F "issuing_state=AUS" \ -F "services=aus_australia_visa" \ -F "vendor_data=user-1234" \ -F "consent=true" \ -F "first_name=John" \ -F "last_name=Doe" \ -F "date_of_birth=1990-01-01" \ -F "passport_number=SAMPLE-PASS-12345" ``` Every successful call returns HTTP `200`. The **`outcome_code`** field tells you what actually happened — distinguishing, for example, a real biometric mismatch (`BIOMETRIC_NO_MATCH`) from a selfie that could not be read (`BIOMETRIC_IMAGE_UNUSABLE`). The `status` shown is the default feature status; your configured [Partial Match / No Match actions](/core-technology/database-validation/database-validation-warnings) can override it. **`MATCH`** — The registry confirmed the identity and every checked field matched. ```json 200 OK — MATCH theme={null} { "request_id": "req_01H…", "status": "Approved", "issuing_state": "AUS", "match_type": "full_match", "validations": [ { "outcome_code": "MATCH", "service_id": "aus_australia_visa", "service_name": "DVS - Australia Visa", "source_data": { "date_of_birth": "1990-01-01", "first_name": "John", "identification_number": "SAMPLE-ID-12345", "last_name": "Doe" }, "validation": { "date_of_birth": "full_match", "full_name": "full_match", "identification_number": "full_match" } } ] } ``` **`PARTIAL_MATCH`** — The identification number was found but one or more personal fields (usually name or date of birth) did not fully match. ```json 200 OK — PARTIAL_MATCH theme={null} { "request_id": "req_01H…", "status": "In Review", "issuing_state": "AUS", "match_type": "partial_match", "validations": [ { "outcome_code": "PARTIAL_MATCH", "service_id": "aus_australia_visa", "service_name": "DVS - Australia Visa", "source_data": { "date_of_birth": "1990-01-01", "first_name": "John", "identification_number": "SAMPLE-ID-12345", "last_name": "Doe" }, "validation": { "date_of_birth": "full_match", "full_name": "no_match", "identification_number": "full_match" } } ] } ``` **`NO_MATCH`** — The registry returned no match for the submitted data. ```json 200 OK — NO_MATCH theme={null} { "request_id": "req_01H…", "status": "Declined", "issuing_state": "AUS", "match_type": "no_match", "validations": [ { "outcome_code": "NO_MATCH", "service_id": "aus_australia_visa", "service_name": "DVS - Australia Visa", "source_data": { "date_of_birth": "NO_MATCH", "full_name": "NO_MATCH", "identification_number": "NO_MATCH" }, "validation": { "date_of_birth": "no_match", "full_name": "no_match", "identification_number": "no_match" } } ] } ``` ## Returned data The exact fields surfaced in `source_data` depend on what the registry returns. The generated example for `aus_australia_visa` currently documents this normalized shape: * `date_of_birth` * `first_name` * `identification_number` * `last_name` ## Pricing & SLAs DVS - Australia Visa queries are billed only when Didit receives a conclusive result from the validation source. * **Per-call price:** \$0.45 USD. * **Billing:** per successful query. You are not charged when the registry is unreachable, when required fields are missing, or when the request is rejected before reaching the source. * **Latency:** typical p95 \< 2 s. * **Availability:** 99.9% per quarter on Didit's side; downstream source availability varies by country and dataset. ## Continue reading * [Australia Database Validation overview](/api-reference/database-validation/australia) * [Database Validation overview](/core-technology/database-validation/overview) * [Outcome Codes](/core-technology/database-validation/database-validation-outcome-codes) # Austria Credit Bureau Source: https://docs.didit.me/api-reference/database-validation/austria/credit-bureau POST /v3/database-validation/ Verifies input data against Credit Header data obtained from a Credit Bureau in Austria. Authoritative real-time identity lookup for Austria. Real-time lookup, pay-per-call.
Verifies input data against Credit Header data obtained from a Credit Bureau in Austria. Didit exposes this service through `POST /v3/database-validation/` so you can verify the submitted data against the authoritative source and receive normalized match results. ## Coverage * **Coverage:** \~ 80% * **Country:** Austria * **Service ID:** `aut_credit_bureau` * **Data domain:** Financial * **Category:** CreditBureau ## Inputs | Field | Required | Example | | --------------------- | -------: | ------------------- | | `first_name` | Yes | `John` | | `last_name` | Yes | `Doe` | | `date_of_birth` | Yes | `1990-01-01` | | `address.street_1` | Yes | `123 Sample Street` | | `address.postal_code` | Yes | `10001` | | `address.street_2` | No | `Unit 4` | | `address.city` | No | `Sample City` | | `address.region` | No | `Sample State` | | `vendor_data` | No | `user-1234` | * **Required inputs:** `first_name`, `last_name`, `date_of_birth`, `address.street_1`, `address.postal_code` * **Optional inputs:** `address.street_2`, `address.city`, `address.region`, `vendor_data` * **Consent:** Required * **Workflow availability:** Available in workflow * **Coverage:** \~ 80% * **Price:** \$1.60 per successful query ## Body parameters ISO 3166-1 alpha-3 country code for this database service. Example: `AUT` Array containing this service ID. Pinning the service keeps the request scoped to this exact database. Example: `aut_credit_bureau` Explicit end-user consent for this service. Example: `true` Given name to validate. Example: `John` Family name to validate. Example: `Doe` Date of birth in `YYYY-MM-DD` format. Example: `1990-01-01` Structured residential address object. Use `street_1`, `street_2`, `city`, `region`, `postal_code`, and `country`. A complete legacy address string is still accepted but not recommended. Example: `{"street_1":"123 Sample Street","street_2":"Unit 4","city":"Sample City","region":"Sample State","postal_code":"10001","country":"US"}` Your stable user reference for this person, such as your internal user ID. Didit uses it to link standalone checks to the same end user and reduce duplicate-detection noise. Example: `user-1234` ## Input rules & validation notes * For address services, send structured address fields instead of a single `address` string when possible. * `address.street_1` is the street address, including street number and street type. * `address.street_2` is apartment, unit, building, floor, or extra address line. Send it only when you have it. * `address.city` is city, suburb, district, locality, or neighborhood. * `address.region` is state, province, region, or town. * `address.postal_code` is postcode or postal code. * Address-based database services require at least street address and postal code; requests rejected before source lookup are not charged. ## How to call it ```bash cURL theme={null} curl -X POST "https://verification.didit.me/v3/database-validation/" \ -H "x-api-key: YOUR_API_KEY" \ -F "issuing_state=AUT" \ -F "services=aut_credit_bureau" \ -F "vendor_data=user-1234" \ -F "consent=true" \ -F "first_name=John" \ -F "last_name=Doe" \ -F "date_of_birth=1990-01-01" \ -F 'address={"street_1":"123 Sample Street","street_2":"Unit 4","city":"Sample City","region":"Sample State","postal_code":"10001","country":"US"}' ``` Every successful call returns HTTP `200`. The **`outcome_code`** field tells you what actually happened — distinguishing, for example, a real biometric mismatch (`BIOMETRIC_NO_MATCH`) from a selfie that could not be read (`BIOMETRIC_IMAGE_UNUSABLE`). The `status` shown is the default feature status; your configured [Partial Match / No Match actions](/core-technology/database-validation/database-validation-warnings) can override it. **`MATCH`** — The registry confirmed the identity and every checked field matched. ```json 200 OK — MATCH theme={null} { "request_id": "req_01H…", "status": "Approved", "issuing_state": "AUT", "match_type": "full_match", "validations": [ { "outcome_code": "MATCH", "service_id": "aut_credit_bureau", "service_name": "Austria Credit Bureau", "source_data": { "address": "123 Sample Street", "date_of_birth": "1990-01-01", "first_name": "John", "last_name": "Doe" }, "validation": { "address": "full_match", "date_of_birth": "full_match", "full_name": "full_match" } } ] } ``` **`PARTIAL_MATCH`** — The identification number was found but one or more personal fields (usually name or date of birth) did not fully match. ```json 200 OK — PARTIAL_MATCH theme={null} { "request_id": "req_01H…", "status": "In Review", "issuing_state": "AUT", "match_type": "partial_match", "validations": [ { "outcome_code": "PARTIAL_MATCH", "service_id": "aut_credit_bureau", "service_name": "Austria Credit Bureau", "source_data": { "address": "123 Sample Street", "date_of_birth": "1990-01-01", "first_name": "John", "last_name": "Doe" }, "validation": { "address": "full_match", "date_of_birth": "full_match", "full_name": "no_match" } } ] } ``` **`NO_MATCH`** — The registry returned no match for the submitted data. ```json 200 OK — NO_MATCH theme={null} { "request_id": "req_01H…", "status": "Declined", "issuing_state": "AUT", "match_type": "no_match", "validations": [ { "outcome_code": "NO_MATCH", "service_id": "aut_credit_bureau", "service_name": "Austria Credit Bureau", "source_data": { "address": "NO_MATCH", "date_of_birth": "NO_MATCH", "full_name": "NO_MATCH" }, "validation": { "address": "no_match", "date_of_birth": "no_match", "full_name": "no_match" } } ] } ``` ## Returned data The exact fields surfaced in `source_data` depend on what the registry returns. The generated example for `aut_credit_bureau` currently documents this normalized shape: * `address` * `date_of_birth` * `first_name` * `last_name` ## Pricing & SLAs Austria Credit Bureau queries are billed only when Didit receives a conclusive result from the validation source. * **Per-call price:** \$1.60 USD. * **Billing:** per successful query. You are not charged when the registry is unreachable, when required fields are missing, or when the request is rejected before reaching the source. * **Latency:** typical p95 \< 2 s. * **Availability:** 99.9% per quarter on Didit's side; downstream source availability varies by country and dataset. ## Continue reading * [Austria Database Validation overview](/api-reference/database-validation/austria) * [Database Validation overview](/core-technology/database-validation/overview) * [Outcome Codes](/core-technology/database-validation/database-validation-outcome-codes) # Bolivia - CI verification Source: https://docs.didit.me/api-reference/database-validation/bolivia/cedula POST /v3/database-validation/ Verifies Bolivian Carnet de Identidad data against SEGIP government records. Authoritative real-time identity lookup for Bolivia. Real-time lookup, pay-per-call.
Verifies Bolivian Carnet de Identidad data against SEGIP government records. Didit exposes this service through `POST /v3/database-validation/` so you can verify the submitted data against the authoritative source and receive normalized match results. ## Coverage * **Coverage:** 90-95% * **Country:** Bolivia * **Service ID:** `bol_cedula` * **Data domain:** Identity * **Category:** NationalIDRegistry ## Inputs | Field | Required | Example | | ----------------- | -------: | ------------ | | `document_number` | Yes | `111111` | | `date_of_birth` | Yes | `1990-01-01` | | `first_name` | No | `John` | | `last_name` | No | `Doe` | | `vendor_data` | No | `user-1234` | * **Required inputs:** `document_number`, `date_of_birth` * **Optional inputs:** `first_name`, `last_name`, `vendor_data` * **Consent:** Not required * **Workflow availability:** Available in workflow * **Coverage:** 90-95% * **Price:** \$0.20 per successful query ## Body parameters ISO 3166-1 alpha-3 country code for this database service. Example: `BOL` Array containing this service ID. Pinning the service keeps the request scoped to this exact database. Example: `bol_cedula` Document number extracted from or provided by the user. Example: `111111` Date of birth in `YYYY-MM-DD` format. Example: `1990-01-01` Given name to validate. Example: `John` Family name to validate. Example: `Doe` Your stable user reference for this person, such as your internal user ID. Didit uses it to link standalone checks to the same end user and reduce duplicate-detection noise. Example: `user-1234` ## Input rules & validation notes * Bolivian CI (6-10 digits) * `document_number` must contain digits only; remove spaces, hyphens, and punctuation before sending the request. * `document_number` must be 6-10 characters long. ## How to call it ```bash cURL theme={null} curl -X POST "https://verification.didit.me/v3/database-validation/" \ -H "x-api-key: YOUR_API_KEY" \ -F "issuing_state=BOL" \ -F "services=bol_cedula" \ -F "vendor_data=user-1234" \ -F "document_number=111111" \ -F "date_of_birth=1990-01-01" ``` Every successful call returns HTTP `200`. The **`outcome_code`** field tells you what actually happened — distinguishing, for example, a real biometric mismatch (`BIOMETRIC_NO_MATCH`) from a selfie that could not be read (`BIOMETRIC_IMAGE_UNUSABLE`). The `status` shown is the default feature status; your configured [Partial Match / No Match actions](/core-technology/database-validation/database-validation-warnings) can override it. **`MATCH`** — The registry confirmed the identity and every checked field matched. ```json 200 OK — MATCH theme={null} { "request_id": "req_01H…", "status": "Approved", "issuing_state": "BOL", "match_type": "full_match", "validations": [ { "outcome_code": "MATCH", "service_id": "bol_cedula", "service_name": "Bolivia - CI verification", "source_data": { "date_of_birth": "1990-01-01", "first_name": "John", "full_name": "John Doe", "identification_number": "SAMPLE-ID-12345", "last_name": "Doe" }, "validation": { "date_of_birth": "full_match", "identification_number": "full_match" } } ] } ``` **`PARTIAL_MATCH`** — The identification number was found but one or more personal fields (usually name or date of birth) did not fully match. ```json 200 OK — PARTIAL_MATCH theme={null} { "request_id": "req_01H…", "status": "In Review", "issuing_state": "BOL", "match_type": "partial_match", "validations": [ { "outcome_code": "PARTIAL_MATCH", "service_id": "bol_cedula", "service_name": "Bolivia - CI verification", "source_data": { "date_of_birth": "1990-01-01", "first_name": "John", "full_name": "John Doe", "identification_number": "SAMPLE-ID-12345", "last_name": "Doe" }, "validation": { "date_of_birth": "no_match", "identification_number": "full_match" } } ] } ``` **`NO_MATCH`** — The registry returned no match for the submitted data. ```json 200 OK — NO_MATCH theme={null} { "request_id": "req_01H…", "status": "Declined", "issuing_state": "BOL", "match_type": "no_match", "validations": [ { "outcome_code": "NO_MATCH", "service_id": "bol_cedula", "service_name": "Bolivia - CI verification", "source_data": { "date_of_birth": "NO_MATCH", "identification_number": "NO_MATCH" }, "validation": { "date_of_birth": "no_match", "identification_number": "no_match" } } ] } ``` ## Returned data The exact fields surfaced in `source_data` depend on what the registry returns. The generated example for `bol_cedula` currently documents this normalized shape: * `date_of_birth` * `first_name` * `full_name` * `identification_number` * `last_name` ## Pricing & SLAs Bolivia - CI verification queries are billed only when Didit receives a conclusive result from the validation source. * **Per-call price:** \$0.20 USD. * **Billing:** per successful query. You are not charged when the registry is unreachable, when required fields are missing, or when the request is rejected before reaching the source. * **Latency:** typical p95 \< 2 s. * **Availability:** 99.9% per quarter on Didit's side; downstream source availability varies by country and dataset. ## Continue reading * [Bolivia Database Validation overview](/api-reference/database-validation/bolivia) * [Database Validation overview](/core-technology/database-validation/overview) * [Outcome Codes](/core-technology/database-validation/database-validation-outcome-codes) # Brazil - CNH QR code + face match (Datavalid) Source: https://docs.didit.me/api-reference/database-validation/brazil/cnh-facial-qrcode POST /v3/database-validation/ SERPRO Datavalid v4 pf-facial-qrcode — decodes the QR code printed on Brazilian CNH driver licences (physical or digital, issued since May 2017), validates CPF + name + date of birth against Receita Federal, and matches the live selfie against the CNH portrait stored at Senatran. Authoritative real-time identity lookup for Brazil. Real-time lookup, pay-per-call.
SERPRO Datavalid v4 pf-facial-qrcode — decodes the QR code printed on Brazilian CNH driver licences (physical or digital, issued since May 2017), validates CPF + name + date of birth against Receita Federal, and matches the live selfie against the CNH portrait stored at Senatran. Didit exposes this service through `POST /v3/database-validation/` so you can verify the submitted data against the authoritative source and receive normalized match results. ## Coverage * **Coverage:** — * **Country:** Brazil * **Service ID:** `bra_cnh_facial_qrcode` * **Data domain:** Biometric * **Category:** DriverLicence ## Inputs | Field | Required | Example | | ------------------- | -------: | -------------------------------------------------------- | | `tax_number` | Yes | `11111111111` | | `selfie` | Yes | `@./selfie.jpg` | | `cnh_qr_code_image` | Yes | `data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAEAAAAB` | | `first_name` | No | `John` | | `last_name` | No | `Doe` | | `date_of_birth` | No | `1990-01-01` | | `vendor_data` | No | `user-1234` | * **Required inputs:** `tax_number`, `selfie`, `cnh_qr_code_image` * **Optional inputs:** `first_name`, `last_name`, `date_of_birth`, `vendor_data` * **Consent:** Required * **Workflow availability:** Available in workflow * **Coverage:** — * **Price:** \$0.50 per successful query ## Body parameters ISO 3166-1 alpha-3 country code for this database service. Example: `BRA` Array containing this service ID. Pinning the service keeps the request scoped to this exact database. Example: `bra_cnh_facial_qrcode` Explicit end-user consent for this service. Example: `true` Tax or fiscal identification number. Example: `11111111111` Selfie image file to upload for biometric database validation. Accepted formats: JPEG, PNG, or WebP. Example: `@./selfie.jpg` `cnh_qr_code_image` value required by this database service. Example: `data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAEAAAAB` Given name to validate. Example: `John` Family name to validate. Example: `Doe` Date of birth in `YYYY-MM-DD` format. Example: `1990-01-01` Your stable user reference for this person, such as your internal user ID. Didit uses it to link standalone checks to the same end user and reduce duplicate-detection noise. Example: `user-1234` ## Input rules & validation notes * Brazilian CPF (exactly 11 digits) * `tax_number` must contain digits only; remove spaces, hyphens, and punctuation before sending the request. * `tax_number` must be exactly 11 characters long. ## How to call it ```bash cURL theme={null} curl -X POST "https://verification.didit.me/v3/database-validation/" \ -H "x-api-key: YOUR_API_KEY" \ -F "issuing_state=BRA" \ -F "services=bra_cnh_facial_qrcode" \ -F "vendor_data=user-1234" \ -F "consent=true" \ -F "tax_number=11111111111" \ -F "selfie=@./selfie.jpg" \ -F "cnh_qr_code_image=data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAEAAAAB" ``` Every successful call returns HTTP `200`. The **`outcome_code`** field tells you what actually happened — distinguishing, for example, a real biometric mismatch (`BIOMETRIC_NO_MATCH`) from a selfie that could not be read (`BIOMETRIC_IMAGE_UNUSABLE`). The `status` shown is the default feature status; your configured [Partial Match / No Match actions](/core-technology/database-validation/database-validation-warnings) can override it. **`MATCH`** — The registry confirmed the identity and every checked field matched. ```json 200 OK — MATCH theme={null} { "request_id": "req_01H…", "status": "Approved", "issuing_state": "BRA", "match_type": "full_match", "validations": [ { "outcome_code": "MATCH", "service_id": "bra_cnh_facial_qrcode", "service_name": "Brazil - CNH QR code + face match (Datavalid)", "source_data": { "cnh_qrcode": "sample_value", "date_of_birth": "1990-01-01", "face_match_probability": "Altíssima probabilidade", "face_match_score": "0.990", "first_name": "John", "identification_number": "SAMPLE-ID-12345", "last_name": "Doe", "name_match_score": "1.000", "verifications": { "identification_number": true } }, "validation": { "identification_number": "full_match" } } ] } ``` **`NO_MATCH`** — The registry returned no match for the submitted data. ```json 200 OK — NO_MATCH theme={null} { "request_id": "req_01H…", "status": "Declined", "issuing_state": "BRA", "match_type": "no_match", "validations": [ { "outcome_code": "NO_MATCH", "service_id": "bra_cnh_facial_qrcode", "service_name": "Brazil - CNH QR code + face match (Datavalid)", "source_data": { "identification_number": "NO_MATCH" }, "validation": { "identification_number": "no_match" } } ] } ``` **`BIOMETRIC_NO_MATCH`** — The face-match score was below the acceptance threshold - the selfie is not the same person as the registry photo. ```json 200 OK — BIOMETRIC_NO_MATCH theme={null} { "request_id": "req_01H…", "status": "Declined", "issuing_state": "BRA", "match_type": "no_match", "validations": [ { "outcome_code": "BIOMETRIC_NO_MATCH", "service_id": "bra_cnh_facial_qrcode", "service_name": "Brazil - CNH QR code + face match (Datavalid)", "source_data": { "identification_number": "NO_MATCH" }, "validation": { "identification_number": "no_match" } } ] } ``` **`BIOMETRIC_IMAGE_UNUSABLE`** — The selfie could not be processed (empty, no face, low quality, or the registry could not read it). Prompt the user to retake the selfie. ```json 200 OK — BIOMETRIC_IMAGE_UNUSABLE theme={null} { "request_id": "req_01H…", "status": "In Review", "issuing_state": "BRA", "match_type": "no_match", "validations": [ { "outcome_code": "BIOMETRIC_IMAGE_UNUSABLE", "service_id": "bra_cnh_facial_qrcode", "service_name": "Brazil - CNH QR code + face match (Datavalid)", "source_data": { "identification_number": "NO_MATCH" }, "validation": { "identification_number": "no_match" } } ] } ``` ## Returned data The exact fields surfaced in `source_data` depend on what the registry returns. The generated example for `bra_cnh_facial_qrcode` currently documents this normalized shape: * `cnh_qrcode` * `date_of_birth` * `face_match_probability` * `face_match_score` * `first_name` * `identification_number` * `last_name` * `name_match_score` ## Pricing & SLAs Brazil - CNH QR code + face match (Datavalid) queries are billed only when Didit receives a conclusive result from the validation source. * **Per-call price:** \$0.50 USD. * **Billing:** per successful query. You are not charged when the registry is unreachable, when required fields are missing, or when the request is rejected before reaching the source. * **Latency:** typical p95 \< 2 s. * **Availability:** 99.9% per quarter on Didit's side; downstream source availability varies by country and dataset. ## Continue reading * [Brazil Database Validation overview](/api-reference/database-validation/brazil) * [Database Validation overview](/core-technology/database-validation/overview) * [Outcome Codes](/core-technology/database-validation/database-validation-outcome-codes) # Brazil - CPF status check Source: https://docs.didit.me/api-reference/database-validation/brazil/cpf POST /v3/database-validation/ Returns CPF status (regular, suspended, cancelled), name, social name and registration date from Receita Federal via SERPRO. The lookup is keyed by CPF and date of birth. Authoritative real-time identity lookup for Brazil. Real-time lookup, pay-per-call.
Returns CPF status (regular, suspended, cancelled), name, social name and registration date from Receita Federal via SERPRO. The lookup is keyed by CPF and date of birth. Didit exposes this service through `POST /v3/database-validation/` so you can verify the submitted data against the authoritative source and receive normalized match results. ## Coverage * **Coverage:** \~ 100% * **Country:** Brazil * **Service ID:** `bra_cpf` * **Data domain:** Identity * **Category:** TaxRegistry ## Inputs | Field | Required | Example | | --------------- | -------: | ------------- | | `tax_number` | Yes | `11111111111` | | `date_of_birth` | Yes | `1990-01-01` | | `first_name` | No | `John` | | `last_name` | No | `Doe` | | `vendor_data` | No | `user-1234` | * **Required inputs:** `tax_number`, `date_of_birth` * **Optional inputs:** `first_name`, `last_name`, `vendor_data` * **Consent:** Not required * **Workflow availability:** Available in workflow * **Coverage:** \~ 100% * **Price:** \$0.20 per successful query Not every document this service accepts carries the identifier it queries by. When the identifier is not extracted from the document the check is recorded as **not applicable** - no database is queried and you are not charged - which for some countries is a large share of real users. To cover them, also collect the identifier from a Questionnaire answer, a Document AI extraction field, or a value you send when you create the session, and map it on the Database Validation step. ## Body parameters ISO 3166-1 alpha-3 country code for this database service. Example: `BRA` Array containing this service ID. Pinning the service keeps the request scoped to this exact database. Example: `bra_cpf` Tax or fiscal identification number. Example: `11111111111` Date of birth in `YYYY-MM-DD` format. Example: `1990-01-01` Given name to validate. Example: `John` Family name to validate. Example: `Doe` Your stable user reference for this person, such as your internal user ID. Didit uses it to link standalone checks to the same end user and reduce duplicate-detection noise. Example: `user-1234` ## Input rules & validation notes * Brazilian CPF (exactly 11 digits) * `tax_number` must contain digits only; remove spaces, hyphens, and punctuation before sending the request. * `tax_number` must be exactly 11 characters long. ## How to call it ```bash cURL theme={null} curl -X POST "https://verification.didit.me/v3/database-validation/" \ -H "x-api-key: YOUR_API_KEY" \ -F "issuing_state=BRA" \ -F "services=bra_cpf" \ -F "vendor_data=user-1234" \ -F "tax_number=11111111111" \ -F "date_of_birth=1990-01-01" ``` Every successful call returns HTTP `200`. The **`outcome_code`** field tells you what actually happened — distinguishing, for example, a real biometric mismatch (`BIOMETRIC_NO_MATCH`) from a selfie that could not be read (`BIOMETRIC_IMAGE_UNUSABLE`). The `status` shown is the default feature status; your configured [Partial Match / No Match actions](/core-technology/database-validation/database-validation-warnings) can override it. **`MATCH`** — The registry confirmed the identity and every checked field matched. ```json 200 OK — MATCH theme={null} { "request_id": "req_01H…", "status": "Approved", "issuing_state": "BRA", "match_type": "full_match", "validations": [ { "outcome_code": "MATCH", "service_id": "bra_cpf", "service_name": "Brazil - CPF status check", "source_data": { "date_of_birth": "1990-01-01", "first_name": "John", "identification_number": "SAMPLE-ID-12345", "last_name": "Doe", "lgpd_minor": "sample_value", "minor_under_16": "sample_value", "minor_under_18": "sample_value", "registration_date": "1990-01-01" }, "validation": { "date_of_birth": "full_match", "identification_number": "full_match" } } ] } ``` **`PARTIAL_MATCH`** — The identification number was found but one or more personal fields (usually name or date of birth) did not fully match. ```json 200 OK — PARTIAL_MATCH theme={null} { "request_id": "req_01H…", "status": "In Review", "issuing_state": "BRA", "match_type": "partial_match", "validations": [ { "outcome_code": "PARTIAL_MATCH", "service_id": "bra_cpf", "service_name": "Brazil - CPF status check", "source_data": { "date_of_birth": "1990-01-01", "first_name": "John", "identification_number": "SAMPLE-ID-12345", "last_name": "Doe", "lgpd_minor": "sample_value", "minor_under_16": "sample_value", "minor_under_18": "sample_value", "registration_date": "1990-01-01" }, "validation": { "date_of_birth": "no_match", "identification_number": "full_match" } } ] } ``` **`NO_MATCH`** — The registry returned no match for the submitted data. ```json 200 OK — NO_MATCH theme={null} { "request_id": "req_01H…", "status": "Declined", "issuing_state": "BRA", "match_type": "no_match", "validations": [ { "outcome_code": "NO_MATCH", "service_id": "bra_cpf", "service_name": "Brazil - CPF status check", "source_data": { "date_of_birth": "NO_MATCH", "identification_number": "NO_MATCH" }, "validation": { "date_of_birth": "no_match", "identification_number": "no_match" } } ] } ``` ## Returned data The exact fields surfaced in `source_data` depend on what the registry returns. The generated example for `bra_cpf` currently documents this normalized shape: * `date_of_birth` * `first_name` * `identification_number` * `last_name` * `lgpd_minor` * `minor_under_16` * `minor_under_18` * `registration_date` ## Pricing & SLAs Brazil - CPF status check queries are billed only when Didit receives a conclusive result from the validation source. * **Per-call price:** \$0.20 USD. * **Billing:** per successful query. You are not charged when the registry is unreachable, when required fields are missing, or when the request is rejected before reaching the source. * **Latency:** typical p95 \< 2 s. * **Availability:** 99.9% per quarter on Didit's side; downstream source availability varies by country and dataset. ## Continue reading * [Brazil Database Validation overview](/api-reference/database-validation/brazil) * [Database Validation overview](/core-technology/database-validation/overview) * [Outcome Codes](/core-technology/database-validation/database-validation-outcome-codes) # Brazil - CPF + face match (Datavalid) Source: https://docs.didit.me/api-reference/database-validation/brazil/cpf-facial POST /v3/database-validation/ SERPRO Datavalid v4 pf-facial — validates CPF (mandatory) against Receita Federal and matches the live selfie (mandatory) against the CNH portrait stored at Senatran. Optionally screens name and date of birth. Authoritative real-time identity lookup for Brazil. Real-time lookup, pay-per-call.
SERPRO Datavalid v4 pf-facial — validates CPF (mandatory) against Receita Federal and matches the live selfie (mandatory) against the CNH portrait stored at Senatran. Optionally screens name and date of birth. Didit exposes this service through `POST /v3/database-validation/` so you can verify the submitted data against the authoritative source and receive normalized match results. ## Coverage * **Coverage:** \~50% * **Country:** Brazil * **Service ID:** `bra_cpf_facial` * **Data domain:** Biometric * **Category:** NationalIDRegistry Roughly 50% of Brazilian adults — the face-match step relies on the CNH portrait held at Senatran, so only driver-licence holders can be matched. ## Inputs | Field | Required | Example | | --------------- | -------: | --------------- | | `tax_number` | Yes | `11111111111` | | `selfie` | Yes | `@./selfie.jpg` | | `first_name` | No | `John` | | `last_name` | No | `Doe` | | `date_of_birth` | No | `1990-01-01` | | `vendor_data` | No | `user-1234` | * **Required inputs:** `tax_number`, `selfie` * **Optional inputs:** `first_name`, `last_name`, `date_of_birth`, `vendor_data` * **Consent:** Required * **Workflow availability:** Available in workflow * **Coverage:** \~50% * **Price:** \$0.45 per successful query ## Body parameters ISO 3166-1 alpha-3 country code for this database service. Example: `BRA` Array containing this service ID. Pinning the service keeps the request scoped to this exact database. Example: `bra_cpf_facial` Explicit end-user consent for this service. Example: `true` Tax or fiscal identification number. Example: `11111111111` Selfie image file to upload for biometric database validation. Accepted formats: JPEG, PNG, or WebP. Example: `@./selfie.jpg` Given name to validate. Example: `John` Family name to validate. Example: `Doe` Date of birth in `YYYY-MM-DD` format. Example: `1990-01-01` Your stable user reference for this person, such as your internal user ID. Didit uses it to link standalone checks to the same end user and reduce duplicate-detection noise. Example: `user-1234` ## Input rules & validation notes * Brazilian CPF (exactly 11 digits) * `tax_number` must contain digits only; remove spaces, hyphens, and punctuation before sending the request. * `tax_number` must be exactly 11 characters long. ## How to call it ```bash cURL theme={null} curl -X POST "https://verification.didit.me/v3/database-validation/" \ -H "x-api-key: YOUR_API_KEY" \ -F "issuing_state=BRA" \ -F "services=bra_cpf_facial" \ -F "vendor_data=user-1234" \ -F "consent=true" \ -F "tax_number=11111111111" \ -F "selfie=@./selfie.jpg" ``` Every successful call returns HTTP `200`. The **`outcome_code`** field tells you what actually happened — distinguishing, for example, a real biometric mismatch (`BIOMETRIC_NO_MATCH`) from a selfie that could not be read (`BIOMETRIC_IMAGE_UNUSABLE`). The `status` shown is the default feature status; your configured [Partial Match / No Match actions](/core-technology/database-validation/database-validation-warnings) can override it. **`MATCH`** — The registry confirmed the identity and every checked field matched. ```json 200 OK — MATCH theme={null} { "request_id": "req_01H…", "status": "Approved", "issuing_state": "BRA", "match_type": "full_match", "validations": [ { "outcome_code": "MATCH", "service_id": "bra_cpf_facial", "service_name": "Brazil - CPF + face match (Datavalid)", "source_data": { "date_of_birth": "1990-01-01", "face_match_probability": "Altíssima probabilidade", "face_match_score": "0.990", "first_name": "John", "identification_number": "SAMPLE-ID-12345", "last_name": "Doe", "name_match_score": "1.000", "verifications": { "identification_number": true } }, "validation": { "identification_number": "full_match" } } ] } ``` **`NO_MATCH`** — The registry returned no match for the submitted data. ```json 200 OK — NO_MATCH theme={null} { "request_id": "req_01H…", "status": "Declined", "issuing_state": "BRA", "match_type": "no_match", "validations": [ { "outcome_code": "NO_MATCH", "service_id": "bra_cpf_facial", "service_name": "Brazil - CPF + face match (Datavalid)", "source_data": { "identification_number": "NO_MATCH" }, "validation": { "identification_number": "no_match" } } ] } ``` **`BIOMETRIC_NO_MATCH`** — The face-match score was below the acceptance threshold - the selfie is not the same person as the registry photo. ```json 200 OK — BIOMETRIC_NO_MATCH theme={null} { "request_id": "req_01H…", "status": "Declined", "issuing_state": "BRA", "match_type": "no_match", "validations": [ { "outcome_code": "BIOMETRIC_NO_MATCH", "service_id": "bra_cpf_facial", "service_name": "Brazil - CPF + face match (Datavalid)", "source_data": { "identification_number": "NO_MATCH" }, "validation": { "identification_number": "no_match" } } ] } ``` **`BIOMETRIC_IMAGE_UNUSABLE`** — The selfie could not be processed (empty, no face, low quality, or the registry could not read it). Prompt the user to retake the selfie. ```json 200 OK — BIOMETRIC_IMAGE_UNUSABLE theme={null} { "request_id": "req_01H…", "status": "In Review", "issuing_state": "BRA", "match_type": "no_match", "validations": [ { "outcome_code": "BIOMETRIC_IMAGE_UNUSABLE", "service_id": "bra_cpf_facial", "service_name": "Brazil - CPF + face match (Datavalid)", "source_data": { "identification_number": "NO_MATCH" }, "validation": { "identification_number": "no_match" } } ] } ``` ## Returned data The exact fields surfaced in `source_data` depend on what the registry returns. The generated example for `bra_cpf_facial` currently documents this normalized shape: * `date_of_birth` * `face_match_probability` * `face_match_score` * `first_name` * `identification_number` * `last_name` * `name_match_score` ## Pricing & SLAs Brazil - CPF + face match (Datavalid) queries are billed only when Didit receives a conclusive result from the validation source. * **Per-call price:** \$0.45 USD. * **Billing:** per successful query. You are not charged when the registry is unreachable, when required fields are missing, or when the request is rejected before reaching the source. * **Latency:** typical p95 \< 2 s. * **Availability:** 99.9% per quarter on Didit's side; downstream source availability varies by country and dataset. ## About this source This is the official government source: [SERPRO](https://www.serpro.gov.br) Datavalid, operated by the Brazilian federal data-processing service. The CPF is checked against Receita Federal, and the selfie is matched against the portrait held for that person at Senatran — the national driver-licensing registry. Because the portrait comes from the CNH (driver's licence) record, only people who hold a CNH have a face on file. That is what caps coverage at roughly 50% of the adult population: the data is authoritative, but it is missing for every Brazilian who has never held a driver's licence. **Need broader coverage?** Use [BRA - Unico IDCloud (CPF + selfie)](/api-reference/database-validation/brazil/unico-idcloud) instead. It reaches about 96% of Brazilian adults through Unico's private biometric registry, and costs \$0.20 against \$0.45 here. Choose Datavalid when you specifically need the government registry as your source of truth; choose IDCloud when you need to verify everyone. ## Continue reading * [Brazil Database Validation overview](/api-reference/database-validation/brazil) * [Database Validation overview](/core-technology/database-validation/overview) * [Outcome Codes](/core-technology/database-validation/database-validation-outcome-codes) # Brazil Residential Source: https://docs.didit.me/api-reference/database-validation/brazil/residential POST /v3/database-validation/ Verifies against a combined database of electoral registrations. Authoritative real-time identity lookup for Brazil. Real-time lookup, pay-per-call.
Verifies against a combined database of electoral registrations. Didit exposes this service through `POST /v3/database-validation/` so you can verify the submitted data against the authoritative source and receive normalized match results. ## Coverage * **Coverage:** \~ 95% * **Country:** Brazil * **Service ID:** `bra_residential` * **Data domain:** Address * **Category:** Residential ## Inputs | Field | Required | Example | | --------------------- | -------: | ------------------- | | `first_name` | Yes | `John` | | `last_name` | Yes | `Doe` | | `date_of_birth` | Yes | `1990-01-01` | | `address.street_1` | Yes | `123 Sample Street` | | `address.postal_code` | Yes | `10001` | | `tax_number` | Yes | `11111111111` | | `address.street_2` | No | `Unit 4` | | `address.city` | No | `Sample City` | | `address.region` | No | `Sample State` | | `vendor_data` | No | `user-1234` | * **Required inputs:** `first_name`, `last_name`, `date_of_birth`, `address.street_1`, `address.postal_code`, `tax_number` * **Optional inputs:** `address.street_2`, `address.city`, `address.region`, `vendor_data` * **Consent:** Not required * **Workflow availability:** Available in workflow * **Coverage:** \~ 95% * **Price:** \$0.35 per successful query Not every document this service accepts carries the identifier it queries by. When the identifier is not extracted from the document the check is recorded as **not applicable** - no database is queried and you are not charged - which for some countries is a large share of real users. To cover them, also collect the identifier from a Questionnaire answer, a Document AI extraction field, or a value you send when you create the session, and map it on the Database Validation step. ## Body parameters ISO 3166-1 alpha-3 country code for this database service. Example: `BRA` Array containing this service ID. Pinning the service keeps the request scoped to this exact database. Example: `bra_residential` Given name to validate. Example: `John` Family name to validate. Example: `Doe` Date of birth in `YYYY-MM-DD` format. Example: `1990-01-01` Structured residential address object. Use `street_1`, `street_2`, `city`, `region`, `postal_code`, and `country`. A complete legacy address string is still accepted but not recommended. Example: `{"street_1":"123 Sample Street","street_2":"Unit 4","city":"Sample City","region":"Sample State","postal_code":"10001","country":"US"}` Tax or fiscal identification number. Example: `11111111111` Your stable user reference for this person, such as your internal user ID. Didit uses it to link standalone checks to the same end user and reduce duplicate-detection noise. Example: `user-1234` ## Input rules & validation notes * Brazilian CPF (exactly 11 digits) * `tax_number` must contain digits only; remove spaces, hyphens, and punctuation before sending the request. * `tax_number` must be exactly 11 characters long. * For address services, send structured address fields instead of a single `address` string when possible. * `address.street_1` is the street address, including street number and street type. * `address.street_2` is apartment, unit, building, floor, or extra address line. Send it only when you have it. * `address.city` is city, suburb, district, locality, or neighborhood. * `address.region` is state, province, region, or town. * `address.postal_code` is postcode or postal code. * Address-based database services require at least street address and postal code; requests rejected before source lookup are not charged. ## How to call it ```bash cURL theme={null} curl -X POST "https://verification.didit.me/v3/database-validation/" \ -H "x-api-key: YOUR_API_KEY" \ -F "issuing_state=BRA" \ -F "services=bra_residential" \ -F "vendor_data=user-1234" \ -F "first_name=John" \ -F "last_name=Doe" \ -F "date_of_birth=1990-01-01" \ -F 'address={"street_1":"123 Sample Street","street_2":"Unit 4","city":"Sample City","region":"Sample State","postal_code":"10001","country":"US"}' \ -F "tax_number=11111111111" ``` Every successful call returns HTTP `200`. The **`outcome_code`** field tells you what actually happened — distinguishing, for example, a real biometric mismatch (`BIOMETRIC_NO_MATCH`) from a selfie that could not be read (`BIOMETRIC_IMAGE_UNUSABLE`). The `status` shown is the default feature status; your configured [Partial Match / No Match actions](/core-technology/database-validation/database-validation-warnings) can override it. **`MATCH`** — The registry confirmed the identity and every checked field matched. ```json 200 OK — MATCH theme={null} { "request_id": "req_01H…", "status": "Approved", "issuing_state": "BRA", "match_type": "full_match", "validations": [ { "outcome_code": "MATCH", "service_id": "bra_residential", "service_name": "Brazil Residential", "source_data": { "address": "123 Sample Street", "date_of_birth": "1990-01-01", "first_name": "John", "identification_number": "SAMPLE-ID-12345", "last_name": "Doe" }, "validation": { "address": "full_match", "date_of_birth": "full_match", "full_name": "full_match", "identification_number": "full_match" } } ] } ``` **`PARTIAL_MATCH`** — The identification number was found but one or more personal fields (usually name or date of birth) did not fully match. ```json 200 OK — PARTIAL_MATCH theme={null} { "request_id": "req_01H…", "status": "In Review", "issuing_state": "BRA", "match_type": "partial_match", "validations": [ { "outcome_code": "PARTIAL_MATCH", "service_id": "bra_residential", "service_name": "Brazil Residential", "source_data": { "address": "123 Sample Street", "date_of_birth": "1990-01-01", "first_name": "John", "identification_number": "SAMPLE-ID-12345", "last_name": "Doe" }, "validation": { "address": "full_match", "date_of_birth": "full_match", "full_name": "no_match", "identification_number": "full_match" } } ] } ``` **`NO_MATCH`** — The registry returned no match for the submitted data. ```json 200 OK — NO_MATCH theme={null} { "request_id": "req_01H…", "status": "Declined", "issuing_state": "BRA", "match_type": "no_match", "validations": [ { "outcome_code": "NO_MATCH", "service_id": "bra_residential", "service_name": "Brazil Residential", "source_data": { "address": "NO_MATCH", "date_of_birth": "NO_MATCH", "full_name": "NO_MATCH", "identification_number": "NO_MATCH" }, "validation": { "address": "no_match", "date_of_birth": "no_match", "full_name": "no_match", "identification_number": "no_match" } } ] } ``` ## Returned data The exact fields surfaced in `source_data` depend on what the registry returns. The generated example for `bra_residential` currently documents this normalized shape: * `address` * `date_of_birth` * `first_name` * `identification_number` * `last_name` ## Pricing & SLAs Brazil Residential queries are billed only when Didit receives a conclusive result from the validation source. * **Per-call price:** \$0.35 USD. * **Billing:** per successful query. You are not charged when the registry is unreachable, when required fields are missing, or when the request is rejected before reaching the source. * **Latency:** typical p95 \< 2 s. * **Availability:** 99.9% per quarter on Didit's side; downstream source availability varies by country and dataset. ## Continue reading * [Brazil Database Validation overview](/api-reference/database-validation/brazil) * [Database Validation overview](/core-technology/database-validation/overview) * [Outcome Codes](/core-technology/database-validation/database-validation-outcome-codes) # Brazil Tax Registration (CPF/CNPJ) Source: https://docs.didit.me/api-reference/database-validation/brazil/tax-registration POST /v3/database-validation/ Verifies against the CPF/CNPJ database. Authoritative real-time identity lookup for Brazil. Real-time lookup, pay-per-call.
Verifies against the CPF/CNPJ database. Didit exposes this service through `POST /v3/database-validation/` so you can verify the submitted data against the authoritative source and receive normalized match results. ## Coverage * **Coverage:** \~ 100% * **Country:** Brazil * **Service ID:** `bra_tax_registration` * **Data domain:** Financial * **Category:** TaxRegistry ## Inputs | Field | Required | Example | | --------------- | -------: | ------------- | | `first_name` | Yes | `John` | | `last_name` | Yes | `Doe` | | `date_of_birth` | Yes | `1990-01-01` | | `tax_number` | Yes | `11111111111` | | `vendor_data` | No | `user-1234` | * **Required inputs:** `first_name`, `last_name`, `date_of_birth`, `tax_number` * **Optional inputs:** `vendor_data` * **Consent:** Not required * **Workflow availability:** Available in workflow * **Coverage:** \~ 100% * **Price:** \$0.15 per successful query Not every document this service accepts carries the identifier it queries by. When the identifier is not extracted from the document the check is recorded as **not applicable** - no database is queried and you are not charged - which for some countries is a large share of real users. To cover them, also collect the identifier from a Questionnaire answer, a Document AI extraction field, or a value you send when you create the session, and map it on the Database Validation step. ## Body parameters ISO 3166-1 alpha-3 country code for this database service. Example: `BRA` Array containing this service ID. Pinning the service keeps the request scoped to this exact database. Example: `bra_tax_registration` Given name to validate. Example: `John` Family name to validate. Example: `Doe` Date of birth in `YYYY-MM-DD` format. Example: `1990-01-01` Tax or fiscal identification number. Example: `11111111111` Your stable user reference for this person, such as your internal user ID. Didit uses it to link standalone checks to the same end user and reduce duplicate-detection noise. Example: `user-1234` ## Input rules & validation notes * Brazilian CPF (exactly 11 digits) * `tax_number` must contain digits only; remove spaces, hyphens, and punctuation before sending the request. * `tax_number` must be exactly 11 characters long. ## How to call it ```bash cURL theme={null} curl -X POST "https://verification.didit.me/v3/database-validation/" \ -H "x-api-key: YOUR_API_KEY" \ -F "issuing_state=BRA" \ -F "services=bra_tax_registration" \ -F "vendor_data=user-1234" \ -F "first_name=John" \ -F "last_name=Doe" \ -F "date_of_birth=1990-01-01" \ -F "tax_number=11111111111" ``` Every successful call returns HTTP `200`. The **`outcome_code`** field tells you what actually happened — distinguishing, for example, a real biometric mismatch (`BIOMETRIC_NO_MATCH`) from a selfie that could not be read (`BIOMETRIC_IMAGE_UNUSABLE`). The `status` shown is the default feature status; your configured [Partial Match / No Match actions](/core-technology/database-validation/database-validation-warnings) can override it. **`MATCH`** — The registry confirmed the identity and every checked field matched. ```json 200 OK — MATCH theme={null} { "request_id": "req_01H…", "status": "Approved", "issuing_state": "BRA", "match_type": "full_match", "validations": [ { "outcome_code": "MATCH", "service_id": "bra_tax_registration", "service_name": "Brazil Tax Registration (CPF/CNPJ)", "source_data": { "date_of_birth": "1990-01-01", "identification_number": "SAMPLE-ID-12345", "name_match_score": "1.000", "verifications": { "date_of_birth": true, "full_name": true, "identification_number": true } }, "validation": { "date_of_birth": "full_match", "full_name": "full_match", "identification_number": "full_match" } } ] } ``` **`PARTIAL_MATCH`** — The identification number was found but one or more personal fields (usually name or date of birth) did not fully match. ```json 200 OK — PARTIAL_MATCH theme={null} { "request_id": "req_01H…", "status": "In Review", "issuing_state": "BRA", "match_type": "partial_match", "validations": [ { "outcome_code": "PARTIAL_MATCH", "service_id": "bra_tax_registration", "service_name": "Brazil Tax Registration (CPF/CNPJ)", "source_data": { "date_of_birth": "1990-01-01", "identification_number": "SAMPLE-ID-12345", "name_match_score": "1.000", "verifications": { "date_of_birth": true, "full_name": false, "identification_number": true } }, "validation": { "date_of_birth": "full_match", "full_name": "no_match", "identification_number": "full_match" } } ] } ``` **`NO_MATCH`** — The registry returned no match for the submitted data. ```json 200 OK — NO_MATCH theme={null} { "request_id": "req_01H…", "status": "Declined", "issuing_state": "BRA", "match_type": "no_match", "validations": [ { "outcome_code": "NO_MATCH", "service_id": "bra_tax_registration", "service_name": "Brazil Tax Registration (CPF/CNPJ)", "source_data": { "date_of_birth": "NO_MATCH", "full_name": "NO_MATCH", "identification_number": "NO_MATCH" }, "validation": { "date_of_birth": "no_match", "full_name": "no_match", "identification_number": "no_match" } } ] } ``` ## Returned data The exact fields surfaced in `source_data` depend on what the registry returns. The generated example for `bra_tax_registration` currently documents this normalized shape: * `date_of_birth` * `identification_number` * `name_match_score` ## Pricing & SLAs Brazil Tax Registration (CPF/CNPJ) queries are billed only when Didit receives a conclusive result from the validation source. * **Per-call price:** \$0.15 USD. * **Billing:** per successful query. You are not charged when the registry is unreachable, when required fields are missing, or when the request is rejected before reaching the source. * **Latency:** typical p95 \< 2 s. * **Availability:** 99.9% per quarter on Didit's side; downstream source availability varies by country and dataset. ## Continue reading * [Brazil Database Validation overview](/api-reference/database-validation/brazil) * [Database Validation overview](/core-technology/database-validation/overview) * [Outcome Codes](/core-technology/database-validation/database-validation-outcome-codes) # BRA - Unico IDCloud (CPF + selfie) Source: https://docs.didit.me/api-reference/database-validation/brazil/unico-idcloud POST /v3/database-validation/ Unico IDCloud biometric validation: matches the user's selfie against the face on record for their CPF and returns whether it is the same person, not the same person, or inconclusive. Authoritative real-time identity lookup for Brazil. Real-time lookup, pay-per-call.
Unico IDCloud biometric validation: matches the user's selfie against the face on record for their CPF and returns whether it is the same person, not the same person, or inconclusive. Didit exposes this service through `POST /v3/database-validation/` so you can verify the submitted data against the authoritative source and receive normalized match results. ## Coverage * **Coverage:** 96% * **Country:** Brazil * **Service ID:** `bra_unico_idcloud` * **Data domain:** Identity * **Category:** BiometricRiskScore About 96% of Brazilian CPF holders resolve to a biometric record in Unico's registry — roughly double the reach of the government face-match source, [Datavalid](/api-reference/database-validation/brazil/cpf-facial), at about 50%. ## Inputs | Field | Required | Example | | --------------- | -------: | --------------- | | `tax_number` | Yes | `11111111111` | | `selfie` | Yes | `@./selfie.jpg` | | `first_name` | No | `John` | | `last_name` | No | `Doe` | | `full_name` | No | `John Doe` | | `date_of_birth` | No | `1990-01-01` | | `vendor_data` | No | `user-1234` | * **Required inputs:** `tax_number`, `selfie` * **Optional inputs:** `first_name`, `last_name`, `full_name`, `date_of_birth`, `vendor_data` * **Consent:** Required * **Workflow availability:** Available in workflow * **Coverage:** 96% * **Price:** \$0.20 per successful query ## Body parameters ISO 3166-1 alpha-3 country code for this database service. Example: `BRA` Array containing this service ID. Pinning the service keeps the request scoped to this exact database. Example: `bra_unico_idcloud` Explicit end-user consent for this service. Example: `true` Tax or fiscal identification number. Example: `11111111111` Selfie image file to upload for biometric database validation. Accepted formats: JPEG, PNG, or WebP. Example: `@./selfie.jpg` Given name to validate. Example: `John` Family name to validate. Example: `Doe` Full legal name to validate. Example: `John Doe` Date of birth in `YYYY-MM-DD` format. Example: `1990-01-01` Your stable user reference for this person, such as your internal user ID. Didit uses it to link standalone checks to the same end user and reduce duplicate-detection noise. Example: `user-1234` ## Input rules & validation notes * Brazilian CPF (exactly 11 digits) * `tax_number` must contain digits only; remove spaces, hyphens, and punctuation before sending the request. * `tax_number` must be exactly 11 characters long. ## How to call it ```bash cURL theme={null} curl -X POST "https://verification.didit.me/v3/database-validation/" \ -H "x-api-key: YOUR_API_KEY" \ -F "issuing_state=BRA" \ -F "services=bra_unico_idcloud" \ -F "vendor_data=user-1234" \ -F "consent=true" \ -F "tax_number=11111111111" \ -F "selfie=@./selfie.jpg" ``` Every successful call returns HTTP `200`. The **`outcome_code`** field tells you what actually happened — distinguishing, for example, a real biometric mismatch (`BIOMETRIC_NO_MATCH`) from a selfie that could not be read (`BIOMETRIC_IMAGE_UNUSABLE`). The `status` shown is the default feature status; your configured [Partial Match / No Match actions](/core-technology/database-validation/database-validation-warnings) can override it. **`MATCH`** — The registry confirmed the identity and every checked field matched. ```json 200 OK — MATCH theme={null} { "request_id": "req_01H…", "status": "Approved", "issuing_state": "BRA", "match_type": "full_match", "validations": [ { "outcome_code": "MATCH", "service_id": "bra_unico_idcloud", "service_name": "BRA - Unico IDCloud (CPF + selfie)", "source_data": { "unico_face_match": "yes" }, "validation": { "identification_number": "full_match" } } ] } ``` **`BIOMETRIC_NO_MATCH`** — The face-match score was below the acceptance threshold - the selfie is not the same person as the registry photo. ```json 200 OK — BIOMETRIC_NO_MATCH theme={null} { "request_id": "req_01H…", "status": "Declined", "issuing_state": "BRA", "match_type": "no_match", "validations": [ { "outcome_code": "BIOMETRIC_NO_MATCH", "service_id": "bra_unico_idcloud", "service_name": "BRA - Unico IDCloud (CPF + selfie)", "source_data": { "identification_number": "NO_MATCH" }, "validation": { "identification_number": "no_match" } } ] } ``` **`INCONCLUSIVE`** — The registry could not determine whether the person matches - the result is genuinely uncertain (they may or may not be in the registry). This is NOT a no-match and NOT a technical image problem; no field is asserted, so match\_type is null and the check is sent to review. ```json 200 OK — INCONCLUSIVE theme={null} { "request_id": "req_01H…", "status": "In Review", "issuing_state": "BRA", "match_type": null, "validations": [ { "outcome_code": "INCONCLUSIVE", "service_id": "bra_unico_idcloud", "service_name": "BRA - Unico IDCloud (CPF + selfie)", "source_data": {}, "validation": {} } ] } ``` ## Returned data The exact fields surfaced in `source_data` depend on what the registry returns. The generated example for `bra_unico_idcloud` currently documents this normalized shape: * `unico_face_match` ## Pricing & SLAs BRA - Unico IDCloud (CPF + selfie) queries are billed only when Didit receives a conclusive result from the validation source. * **Per-call price:** \$0.20 USD. * **Billing:** per successful query. You are not charged when the registry is unreachable, when required fields are missing, or when the request is rejected before reaching the source. * **Latency:** typical p95 \< 2 s. * **Availability:** 99.9% per quarter on Didit's side; downstream source availability varies by country and dataset. ## About this source [Unico](https://unico.io) is a Brazilian IDtech that runs the country's largest private facial-biometric registry. Its IDCloud platform holds more than a billion facial embeddings and adds roughly 35 million new faces every month, fed by the onboarding and re-authentication flows of over 800 Brazilian companies — including four of the five largest banks. That scale is what produces the coverage figure above: a CPF lookup resolves to a biometric record for about 96% of Brazilian adults. Didit has a direct partnership with Unico, so you can query IDCloud through the standard Database Validation API — pay-per-call, with no separate Unico contract, no minimum volume, and no onboarding process. **How this differs from the government registry.** Didit also offers [Brazil - CPF + face match (Datavalid)](/api-reference/database-validation/brazil/cpf-facial), which is the official SERPRO source and the right choice when you specifically need the government registry as your source of truth. IDCloud is the stronger choice for everything else, on two axes you can check: it reaches about 96% of adults against Datavalid's roughly 50%, and it matches against a biometric record the registry maintains itself rather than a portrait taken from a document the user hands you — so it resists both document forgery and stolen-CPF fraud. It is also less than half the price per query. ## Recommended flow for Brazil For most Brazilian use cases you do not need document capture at all. The user gives you a CPF, and a liveness-checked selfie confirms they are the person behind it. Your only text input is the 11-digit CPF — no document photo, and no manually typed name or date of birth. Because no document is read in this flow, Didit has nothing to take the CPF from unless you say where it comes from. Send it in the session's `metadata` when you create the session, and map it as the `tax_number` input of the Database Validation step. In the Business Console that is the step's input mapping; through the workflows API it is the node's `database_validation_field_sources`: ```json theme={null} { "database_validation_countries": {"BRA": {"services": ["bra_unico_idcloud"]}}, "database_validation_field_sources": { "tax_number": {"source": "expected_data", "key": "metadata.cpf"} } } ``` Then create each session with the value under that key: ```json theme={null} {"workflow_id": "", "metadata": {"cpf": "12345678909"}} ``` Without the mapping the step still runs, but it reports `tax_number` as missing and never queries the registry — nothing is billed, and the session's `database_validations` entry carries the reason. Add a [liveness](/core-technology/liveness/overview) step to the same workflow and pick the method that matches your risk appetite — **Passive Liveness** (no user action at all), **3D Flash**, or **3D Action & Flash** (active methods that project light patterns, the last one adding a randomized action). Set it with `face_liveness_method` (`PASSIVE`, `FLASHING`, or `ACTIVE_3D`) in the Business Console or through the workflows API. Whichever you pick, Didit renders the capture step and confirms a real, present person — this is what stops a stored photo or a screen replay from being submitted. Inside a session flow Didit re-uses the liveness selfie automatically — you never handle the image — and reads the CPF from the mapping above. IDCloud then confirms whether that face belongs to the person the CPF belongs to. The step needs only these two inputs; if you also send `full_name` or `date_of_birth` in `metadata` and map them, they are passed to Unico as cross-checks, but they are not required. This CPF-only flow applies to **session and workflow** integrations, where Didit performs the capture and passes the liveness selfie to this service for you. If you call `POST /v3/database-validation/` **directly**, `selfie` is a required file input and you supply the image yourself — see [Database Validation overview](/core-technology/database-validation/overview) for both modes. **Cost:** about \$0.30 per verified user with Passive Liveness — \$0.20 for the IDCloud query plus \$0.10 for the liveness check — or about \$0.35 with an active method, where the liveness check costs \$0.15. Liveness includes a free monthly tier, so early volume costs less; see [pricing](/getting-started/pricing). **Fallback for the roughly 4% without coverage.** When IDCloud returns `INCONCLUSIVE`, the registry could not resolve that CPF to a usable biometric record — typically because the person is not in it. Treat this as "no answer" rather than a failed check, and fall back to full [ID Verification](/core-technology/id-verification/overview): document capture plus face match against the document portrait. Everyone stays verifiable, and you pay for document verification only on the small remainder. **Handling declines.** `BIOMETRIC_NO_MATCH` means the registry actively disagreed — the face does not belong to that CPF. Treat it as a strong negative rather than a prompt to retry: sending the user straight to document capture is exactly the path an impostor wants, since the document is the artefact they control. Genuine false negatives do happen, though — a changed appearance, an old registry photo, or a poor capture — so route these to manual review instead of either auto-approving or dead-ending the user. `BIOMETRIC_IMAGE_UNUSABLE` is different: the selfie simply could not be read, so ask for a fresh one. Decide what each result does to the session with [Partial Match / No Match actions](/core-technology/database-validation/database-validation-warnings), and see [Outcome Codes](/core-technology/database-validation/database-validation-outcome-codes) for the full list. **Returning users.** You only need to pay for a registry lookup once. After a user passes this flow, the liveness selfie is stored against their `vendor_data`, so you can re-verify them later with [Biometric Authentication](/core-technology/biometric-auth/overview) — a liveness check plus a face match against that stored face — for \$0.10, with the same choice of liveness methods. Note that this is for **returning** users specifically: a biometric-authentication session needs a stored face (or a `portrait_image` you supply) and fails at creation if the user has neither, so first-time users still go through the flow above. ## Continue reading * [Brazil Database Validation overview](/api-reference/database-validation/brazil) * [Database Validation overview](/core-technology/database-validation/overview) * [Outcome Codes](/core-technology/database-validation/database-validation-outcome-codes) # Cambodia National ID Source: https://docs.didit.me/api-reference/database-validation/cambodia/national-id POST /v3/database-validation/ Verifies input data against a Government agency database consisting of national identity data of citizens. Authoritative real-time identity lookup for Cambodia. Real-time lookup, pay-per-call.
Verifies input data against a Government agency database consisting of national identity data of citizens. Didit exposes this service through `POST /v3/database-validation/` so you can verify the submitted data against the authoritative source and receive normalized match results. ## Coverage * **Coverage:** \~ 80% * **Country:** Cambodia * **Service ID:** `khm_national_id` * **Data domain:** Identity * **Category:** NationalIDRegistry ## Inputs | Field | Required | Example | | --------------------- | -------: | -------------------- | | `first_name` | Yes | `John` | | `last_name` | Yes | `Doe` | | `date_of_birth` | Yes | `1990-01-01` | | `voter_id` | Yes | `SAMPLE-VOTER-12345` | | `gender` | No | `M` | | `address.street_1` | No | `123 Sample Street` | | `address.street_2` | No | `Unit 4` | | `address.city` | No | `Sample City` | | `address.region` | No | `Sample State` | | `address.postal_code` | No | `10001` | | `vendor_data` | No | `user-1234` | * **Required inputs:** `first_name`, `last_name`, `date_of_birth`, `voter_id` * **Optional inputs:** `gender`, `address.street_1`, `address.street_2`, `address.city`, `address.region`, `address.postal_code`, `vendor_data` * **Consent:** Required * **Workflow availability:** Available in workflow * **Coverage:** \~ 80% * **Price:** \$0.35 per successful query Not every document this service accepts carries the identifier it queries by. When the identifier is not extracted from the document the check is recorded as **not applicable** - no database is queried and you are not charged - which for some countries is a large share of real users. To cover them, also collect the identifier from a Questionnaire answer, a Document AI extraction field, or a value you send when you create the session, and map it on the Database Validation step. ## Body parameters ISO 3166-1 alpha-3 country code for this database service. Example: `KHM` Array containing this service ID. Pinning the service keeps the request scoped to this exact database. Example: `khm_national_id` Explicit end-user consent for this service. Example: `true` Given name to validate. Example: `John` Family name to validate. Example: `Doe` Date of birth in `YYYY-MM-DD` format. Example: `1990-01-01` Voter identifier. Example: `SAMPLE-VOTER-12345` Gender value, when required by the database. Allowed values: `M` (male), `F` (female), `X` (other or unknown). Example: `M` Structured residential address object. Use `street_1`, `street_2`, `city`, `region`, `postal_code`, and `country`. A complete legacy address string is still accepted but not recommended. Example: `{"street_1":"123 Sample Street","street_2":"Unit 4","city":"Sample City","region":"Sample State","postal_code":"10001","country":"US"}` Your stable user reference for this person, such as your internal user ID. Didit uses it to link standalone checks to the same end user and reduce duplicate-detection noise. Example: `user-1234` ## Input rules & validation notes * `address` is optional for this service. You can send one complete `address` string and Didit will split it into structured address elements when possible, or you can send the structured fields explicitly. * `voter_id` must match `(?:\d{8,9}|\d{2}-\d{3}-\d{3})`. * For address services, send structured address fields instead of a single `address` string when possible. * `address.street_1` is the street address, including street number and street type. * `address.street_2` is apartment, unit, building, floor, or extra address line. Send it only when you have it. * `address.city` is city, suburb, district, locality, or neighborhood. * `address.region` is state, province, region, or town. * `address.postal_code` is postcode or postal code. * Address-based database services require at least street address and postal code; requests rejected before source lookup are not charged. ## How to call it ```bash cURL theme={null} curl -X POST "https://verification.didit.me/v3/database-validation/" \ -H "x-api-key: YOUR_API_KEY" \ -F "issuing_state=KHM" \ -F "services=khm_national_id" \ -F "vendor_data=user-1234" \ -F "consent=true" \ -F "first_name=John" \ -F "last_name=Doe" \ -F "date_of_birth=1990-01-01" \ -F "voter_id=SAMPLE-VOTER-12345" ``` Every successful call returns HTTP `200`. The **`outcome_code`** field tells you what actually happened — distinguishing, for example, a real biometric mismatch (`BIOMETRIC_NO_MATCH`) from a selfie that could not be read (`BIOMETRIC_IMAGE_UNUSABLE`). The `status` shown is the default feature status; your configured [Partial Match / No Match actions](/core-technology/database-validation/database-validation-warnings) can override it. **`MATCH`** — The registry confirmed the identity and every checked field matched. ```json 200 OK — MATCH theme={null} { "request_id": "req_01H…", "status": "Approved", "issuing_state": "KHM", "match_type": "full_match", "validations": [ { "outcome_code": "MATCH", "service_id": "khm_national_id", "service_name": "Cambodia National ID", "source_data": { "address": "123 Sample Street", "address_match_score": "1.000", "building_number": "SAMPLE-12345", "city": "Sample City", "date_of_birth": "1990-01-01", "first_name": "John", "full_name": "John Doe", "identification_number": "SAMPLE-ID-12345", "last_name": "Doe", "name_match_score": "1.000", "state": "Sample State", "street": "sample_value", "verifications": { "date_of_birth": true, "full_name": true, "identification_number": true } }, "validation": { "date_of_birth": "full_match", "full_name": "full_match", "identification_number": "full_match" } } ] } ``` **`PARTIAL_MATCH`** — The identification number was found but one or more personal fields (usually name or date of birth) did not fully match. ```json 200 OK — PARTIAL_MATCH theme={null} { "request_id": "req_01H…", "status": "In Review", "issuing_state": "KHM", "match_type": "partial_match", "validations": [ { "outcome_code": "PARTIAL_MATCH", "service_id": "khm_national_id", "service_name": "Cambodia National ID", "source_data": { "address": "123 Sample Street", "address_match_score": "1.000", "building_number": "SAMPLE-12345", "city": "Sample City", "date_of_birth": "1990-01-01", "first_name": "John", "full_name": "John Doe", "identification_number": "SAMPLE-ID-12345", "last_name": "Doe", "name_match_score": "1.000", "state": "Sample State", "street": "sample_value", "verifications": { "date_of_birth": true, "full_name": false, "identification_number": true } }, "validation": { "date_of_birth": "full_match", "full_name": "no_match", "identification_number": "full_match" } } ] } ``` **`NO_MATCH`** — The registry returned no match for the submitted data. ```json 200 OK — NO_MATCH theme={null} { "request_id": "req_01H…", "status": "Declined", "issuing_state": "KHM", "match_type": "no_match", "validations": [ { "outcome_code": "NO_MATCH", "service_id": "khm_national_id", "service_name": "Cambodia National ID", "source_data": { "date_of_birth": "NO_MATCH", "full_name": "NO_MATCH", "identification_number": "NO_MATCH" }, "validation": { "date_of_birth": "no_match", "full_name": "no_match", "identification_number": "no_match" } } ] } ``` ## Returned data The exact fields surfaced in `source_data` depend on what the registry returns. The generated example for `khm_national_id` currently documents this normalized shape: * `address` * `address_match_score` * `building_number` * `city` * `date_of_birth` * `first_name` * `full_name` * `identification_number` * `last_name` * `name_match_score` * `state` * `street` ## Pricing & SLAs Cambodia National ID queries are billed only when Didit receives a conclusive result from the validation source. * **Per-call price:** \$0.35 USD. * **Billing:** per successful query. You are not charged when the registry is unreachable, when required fields are missing, or when the request is rejected before reaching the source. * **Latency:** typical p95 \< 2 s. * **Availability:** 99.9% per quarter on Didit's side; downstream source availability varies by country and dataset. ## Continue reading * [Cambodia Database Validation overview](/api-reference/database-validation/cambodia) * [Database Validation overview](/core-technology/database-validation/overview) * [Outcome Codes](/core-technology/database-validation/database-validation-outcome-codes) # Canada Credit Bureau 2 (Non-FINTRAC) Source: https://docs.didit.me/api-reference/database-validation/canada/credit-bureau-2-non-fintrac POST /v3/database-validation/ Verifies input data against Credit Header data obtained from a Credit Bureau in Canada. This service does not provide FINTRAC required data but can provide additional fraud detection flags. An agency application is required. Authoritative real-time identity lookup for Canada. Real-time lookup, pay-per-call.
Verifies input data against Credit Header data obtained from a Credit Bureau in Canada. This service does not provide FINTRAC required data but can provide additional fraud detection flags. An agency application is required. Didit exposes this service through `POST /v3/database-validation/` so you can verify the submitted data against the authoritative source and receive normalized match results. ## Coverage * **Coverage:** \~ 85% * **Country:** Canada * **Service ID:** `can_credit_bureau_2_non_fintrac` * **Data domain:** Financial * **Category:** CreditBureau ## Inputs | Field | Required | Example | | --------------------- | -------: | ------------------- | | `first_name` | Yes | `John` | | `last_name` | Yes | `Doe` | | `date_of_birth` | Yes | `1990-01-01` | | `address.street_1` | Yes | `123 Sample Street` | | `address.postal_code` | Yes | `10001` | | `address.street_2` | No | `Unit 4` | | `address.city` | No | `Sample City` | | `address.region` | No | `Sample State` | | `vendor_data` | No | `user-1234` | * **Required inputs:** `first_name`, `last_name`, `date_of_birth`, `address.street_1`, `address.postal_code` * **Optional inputs:** `address.street_2`, `address.city`, `address.region`, `vendor_data` * **Consent:** Required * **Workflow availability:** Available in workflow * **Coverage:** \~ 85% * **Price:** \$1.05 per successful query ## Body parameters ISO 3166-1 alpha-3 country code for this database service. Example: `CAN` Array containing this service ID. Pinning the service keeps the request scoped to this exact database. Example: `can_credit_bureau_2_non_fintrac` Explicit end-user consent for this service. Example: `true` Given name to validate. Example: `John` Family name to validate. Example: `Doe` Date of birth in `YYYY-MM-DD` format. Example: `1990-01-01` Structured residential address object. Use `street_1`, `street_2`, `city`, `region`, `postal_code`, and `country`. A complete legacy address string is still accepted but not recommended. Example: `{"street_1":"123 Sample Street","street_2":"Unit 4","city":"Sample City","region":"Sample State","postal_code":"10001","country":"US"}` Your stable user reference for this person, such as your internal user ID. Didit uses it to link standalone checks to the same end user and reduce duplicate-detection noise. Example: `user-1234` ## Input rules & validation notes * For address services, send structured address fields instead of a single `address` string when possible. * `address.street_1` is the street address, including street number and street type. * `address.street_2` is apartment, unit, building, floor, or extra address line. Send it only when you have it. * `address.city` is city, suburb, district, locality, or neighborhood. * `address.region` is state, province, region, or town. * `address.postal_code` is postcode or postal code. * Address-based database services require at least street address and postal code; requests rejected before source lookup are not charged. ## How to call it ```bash cURL theme={null} curl -X POST "https://verification.didit.me/v3/database-validation/" \ -H "x-api-key: YOUR_API_KEY" \ -F "issuing_state=CAN" \ -F "services=can_credit_bureau_2_non_fintrac" \ -F "vendor_data=user-1234" \ -F "consent=true" \ -F "first_name=John" \ -F "last_name=Doe" \ -F "date_of_birth=1990-01-01" \ -F 'address={"street_1":"123 Sample Street","street_2":"Unit 4","city":"Sample City","region":"Sample State","postal_code":"10001","country":"US"}' ``` Every successful call returns HTTP `200`. The **`outcome_code`** field tells you what actually happened — distinguishing, for example, a real biometric mismatch (`BIOMETRIC_NO_MATCH`) from a selfie that could not be read (`BIOMETRIC_IMAGE_UNUSABLE`). The `status` shown is the default feature status; your configured [Partial Match / No Match actions](/core-technology/database-validation/database-validation-warnings) can override it. **`MATCH`** — The registry confirmed the identity and every checked field matched. ```json 200 OK — MATCH theme={null} { "request_id": "req_01H…", "status": "Approved", "issuing_state": "CAN", "match_type": "full_match", "validations": [ { "outcome_code": "MATCH", "service_id": "can_credit_bureau_2_non_fintrac", "service_name": "Canada Credit Bureau 2 (Non-FINTRAC)", "source_data": { "address": "123 Sample Street", "date_of_birth": "1990-01-01", "first_name": "John", "last_name": "Doe" }, "validation": { "address": "full_match", "date_of_birth": "full_match", "full_name": "full_match" } } ] } ``` **`PARTIAL_MATCH`** — The identification number was found but one or more personal fields (usually name or date of birth) did not fully match. ```json 200 OK — PARTIAL_MATCH theme={null} { "request_id": "req_01H…", "status": "In Review", "issuing_state": "CAN", "match_type": "partial_match", "validations": [ { "outcome_code": "PARTIAL_MATCH", "service_id": "can_credit_bureau_2_non_fintrac", "service_name": "Canada Credit Bureau 2 (Non-FINTRAC)", "source_data": { "address": "123 Sample Street", "date_of_birth": "1990-01-01", "first_name": "John", "last_name": "Doe" }, "validation": { "address": "full_match", "date_of_birth": "full_match", "full_name": "no_match" } } ] } ``` **`NO_MATCH`** — The registry returned no match for the submitted data. ```json 200 OK — NO_MATCH theme={null} { "request_id": "req_01H…", "status": "Declined", "issuing_state": "CAN", "match_type": "no_match", "validations": [ { "outcome_code": "NO_MATCH", "service_id": "can_credit_bureau_2_non_fintrac", "service_name": "Canada Credit Bureau 2 (Non-FINTRAC)", "source_data": { "address": "NO_MATCH", "date_of_birth": "NO_MATCH", "full_name": "NO_MATCH" }, "validation": { "address": "no_match", "date_of_birth": "no_match", "full_name": "no_match" } } ] } ``` ## Returned data The exact fields surfaced in `source_data` depend on what the registry returns. The generated example for `can_credit_bureau_2_non_fintrac` currently documents this normalized shape: * `address` * `date_of_birth` * `first_name` * `last_name` ## Pricing & SLAs Canada Credit Bureau 2 (Non-FINTRAC) queries are billed only when Didit receives a conclusive result from the validation source. * **Per-call price:** \$1.05 USD. * **Billing:** per successful query. You are not charged when the registry is unreachable, when required fields are missing, or when the request is rejected before reaching the source. * **Latency:** typical p95 \< 2 s. * **Availability:** 99.9% per quarter on Didit's side; downstream source availability varies by country and dataset. ## Continue reading * [Canada Database Validation overview](/api-reference/database-validation/canada) * [Database Validation overview](/core-technology/database-validation/overview) * [Outcome Codes](/core-technology/database-validation/database-validation-outcome-codes) # Canada Credit Bureau (FINTRAC) Source: https://docs.didit.me/api-reference/database-validation/canada/credit-bureau-fintrac POST /v3/database-validation/ Verifies input data against Credit Header data obtained from a Credit Bureau in Canada and responds with data sufficient to meet FINTRAC requirements. An agency application is required. This service cannot currently be included in a Sequence Package. Authoritative real-time identity lookup for Canada. Real-time lookup, pay-per-call.
Verifies input data against Credit Header data obtained from a Credit Bureau in Canada and responds with data sufficient to meet FINTRAC requirements. An agency application is required. This service cannot currently be included in a Sequence Package. Didit exposes this service through `POST /v3/database-validation/` so you can verify the submitted data against the authoritative source and receive normalized match results. ## Coverage * **Coverage:** \~ 85% * **Country:** Canada * **Service ID:** `can_credit_bureau_fintrac` * **Data domain:** Financial * **Category:** CreditBureau ## Inputs | Field | Required | Example | | --------------------- | -------: | ------------------- | | `first_name` | Yes | `John` | | `last_name` | Yes | `Doe` | | `address.street_1` | Yes | `123 Sample Street` | | `address.postal_code` | Yes | `10001` | | `date_of_birth` | Yes | `1990-01-01` | | `address.street_2` | No | `Unit 4` | | `address.city` | No | `Sample City` | | `address.region` | No | `Sample State` | | `vendor_data` | No | `user-1234` | * **Required inputs:** `first_name`, `last_name`, `address.street_1`, `address.postal_code`, `date_of_birth` * **Optional inputs:** `address.street_2`, `address.city`, `address.region`, `vendor_data` * **Consent:** Required * **Workflow availability:** Available in workflow * **Coverage:** \~ 85% * **Price:** \$2.90 per successful query ## Body parameters ISO 3166-1 alpha-3 country code for this database service. Example: `CAN` Array containing this service ID. Pinning the service keeps the request scoped to this exact database. Example: `can_credit_bureau_fintrac` Explicit end-user consent for this service. Example: `true` Given name to validate. Example: `John` Family name to validate. Example: `Doe` Structured residential address object. Use `street_1`, `street_2`, `city`, `region`, `postal_code`, and `country`. A complete legacy address string is still accepted but not recommended. Example: `{"street_1":"123 Sample Street","street_2":"Unit 4","city":"Sample City","region":"Sample State","postal_code":"10001","country":"US"}` Date of birth in `YYYY-MM-DD` format. Example: `1990-01-01` Your stable user reference for this person, such as your internal user ID. Didit uses it to link standalone checks to the same end user and reduce duplicate-detection noise. Example: `user-1234` ## Input rules & validation notes * For address services, send structured address fields instead of a single `address` string when possible. * `address.street_1` is the street address, including street number and street type. * `address.street_2` is apartment, unit, building, floor, or extra address line. Send it only when you have it. * `address.city` is city, suburb, district, locality, or neighborhood. * `address.region` is state, province, region, or town. * `address.postal_code` is postcode or postal code. * Address-based database services require at least street address and postal code; requests rejected before source lookup are not charged. ## How to call it ```bash cURL theme={null} curl -X POST "https://verification.didit.me/v3/database-validation/" \ -H "x-api-key: YOUR_API_KEY" \ -F "issuing_state=CAN" \ -F "services=can_credit_bureau_fintrac" \ -F "vendor_data=user-1234" \ -F "consent=true" \ -F "first_name=John" \ -F "last_name=Doe" \ -F 'address={"street_1":"123 Sample Street","street_2":"Unit 4","city":"Sample City","region":"Sample State","postal_code":"10001","country":"US"}' \ -F "date_of_birth=1990-01-01" ``` Every successful call returns HTTP `200`. The **`outcome_code`** field tells you what actually happened — distinguishing, for example, a real biometric mismatch (`BIOMETRIC_NO_MATCH`) from a selfie that could not be read (`BIOMETRIC_IMAGE_UNUSABLE`). The `status` shown is the default feature status; your configured [Partial Match / No Match actions](/core-technology/database-validation/database-validation-warnings) can override it. **`MATCH`** — The registry confirmed the identity and every checked field matched. ```json 200 OK — MATCH theme={null} { "request_id": "req_01H…", "status": "Approved", "issuing_state": "CAN", "match_type": "full_match", "validations": [ { "outcome_code": "MATCH", "service_id": "can_credit_bureau_fintrac", "service_name": "Canada Credit Bureau (FINTRAC)", "source_data": { "address": "123 Sample Street", "date_of_birth": "1990-01-01", "first_name": "John", "last_name": "Doe" }, "validation": { "address": "full_match", "date_of_birth": "full_match", "full_name": "full_match" } } ] } ``` **`PARTIAL_MATCH`** — The identification number was found but one or more personal fields (usually name or date of birth) did not fully match. ```json 200 OK — PARTIAL_MATCH theme={null} { "request_id": "req_01H…", "status": "In Review", "issuing_state": "CAN", "match_type": "partial_match", "validations": [ { "outcome_code": "PARTIAL_MATCH", "service_id": "can_credit_bureau_fintrac", "service_name": "Canada Credit Bureau (FINTRAC)", "source_data": { "address": "123 Sample Street", "date_of_birth": "1990-01-01", "first_name": "John", "last_name": "Doe" }, "validation": { "address": "full_match", "date_of_birth": "full_match", "full_name": "no_match" } } ] } ``` **`NO_MATCH`** — The registry returned no match for the submitted data. ```json 200 OK — NO_MATCH theme={null} { "request_id": "req_01H…", "status": "Declined", "issuing_state": "CAN", "match_type": "no_match", "validations": [ { "outcome_code": "NO_MATCH", "service_id": "can_credit_bureau_fintrac", "service_name": "Canada Credit Bureau (FINTRAC)", "source_data": { "address": "NO_MATCH", "date_of_birth": "NO_MATCH", "full_name": "NO_MATCH" }, "validation": { "address": "no_match", "date_of_birth": "no_match", "full_name": "no_match" } } ] } ``` ## Returned data The exact fields surfaced in `source_data` depend on what the registry returns. The generated example for `can_credit_bureau_fintrac` currently documents this normalized shape: * `address` * `date_of_birth` * `first_name` * `last_name` ## Pricing & SLAs Canada Credit Bureau (FINTRAC) queries are billed only when Didit receives a conclusive result from the validation source. * **Per-call price:** \$2.90 USD. * **Billing:** per successful query. You are not charged when the registry is unreachable, when required fields are missing, or when the request is rejected before reaching the source. * **Latency:** typical p95 \< 2 s. * **Availability:** 99.9% per quarter on Didit's side; downstream source availability varies by country and dataset. ## Continue reading * [Canada Database Validation overview](/api-reference/database-validation/canada) * [Database Validation overview](/core-technology/database-validation/overview) * [Outcome Codes](/core-technology/database-validation/database-validation-outcome-codes) # Canada Residential Source: https://docs.didit.me/api-reference/database-validation/canada/residential POST /v3/database-validation/ Verifies input data to mobile network operators phone data. An agency application is required. Authoritative real-time identity lookup for Canada. Real-time lookup, pay-per-call.
Verifies input data to mobile network operators phone data. An agency application is required. Didit exposes this service through `POST /v3/database-validation/` so you can verify the submitted data against the authoritative source and receive normalized match results. ## Coverage * **Coverage:** \~ 90% * **Country:** Canada * **Service ID:** `can_residential` * **Data domain:** Address * **Category:** Residential ## Inputs | Field | Required | Example | | --------------------- | -------: | ------------------- | | `first_name` | Yes | `John` | | `last_name` | Yes | `Doe` | | `address.street_1` | Yes | `123 Sample Street` | | `address.postal_code` | Yes | `10001` | | `phone` | Yes | `+15550101000` | | `date_of_birth` | No | `1990-01-01` | | `address.street_2` | No | `Unit 4` | | `address.city` | No | `Sample City` | | `address.region` | No | `Sample State` | | `vendor_data` | No | `user-1234` | * **Required inputs:** `first_name`, `last_name`, `address.street_1`, `address.postal_code`, `phone` * **Optional inputs:** `date_of_birth`, `address.street_2`, `address.city`, `address.region`, `vendor_data` * **Consent:** Required * **Workflow availability:** Available in workflow * **Coverage:** \~ 90% * **Price:** \$0.25 per successful query ## Body parameters ISO 3166-1 alpha-3 country code for this database service. Example: `CAN` Array containing this service ID. Pinning the service keeps the request scoped to this exact database. Example: `can_residential` Explicit end-user consent for this service. Example: `true` Given name to validate. Example: `John` Family name to validate. Example: `Doe` Structured residential address object. Use `street_1`, `street_2`, `city`, `region`, `postal_code`, and `country`. A complete legacy address string is still accepted but not recommended. Example: `{"street_1":"123 Sample Street","street_2":"Unit 4","city":"Sample City","region":"Sample State","postal_code":"10001","country":"US"}` Phone number in international format. Example: `+15550101000` Date of birth in `YYYY-MM-DD` format. Example: `1990-01-01` Your stable user reference for this person, such as your internal user ID. Didit uses it to link standalone checks to the same end user and reduce duplicate-detection noise. Example: `user-1234` ## Input rules & validation notes * For address services, send structured address fields instead of a single `address` string when possible. * `address.street_1` is the street address, including street number and street type. * `address.street_2` is apartment, unit, building, floor, or extra address line. Send it only when you have it. * `address.city` is city, suburb, district, locality, or neighborhood. * `address.region` is state, province, region, or town. * `address.postal_code` is postcode or postal code. * Address-based database services require at least street address and postal code; requests rejected before source lookup are not charged. ## How to call it ```bash cURL theme={null} curl -X POST "https://verification.didit.me/v3/database-validation/" \ -H "x-api-key: YOUR_API_KEY" \ -F "issuing_state=CAN" \ -F "services=can_residential" \ -F "vendor_data=user-1234" \ -F "consent=true" \ -F "first_name=John" \ -F "last_name=Doe" \ -F 'address={"street_1":"123 Sample Street","street_2":"Unit 4","city":"Sample City","region":"Sample State","postal_code":"10001","country":"US"}' \ -F "phone=+15550101000" ``` Every successful call returns HTTP `200`. The **`outcome_code`** field tells you what actually happened — distinguishing, for example, a real biometric mismatch (`BIOMETRIC_NO_MATCH`) from a selfie that could not be read (`BIOMETRIC_IMAGE_UNUSABLE`). The `status` shown is the default feature status; your configured [Partial Match / No Match actions](/core-technology/database-validation/database-validation-warnings) can override it. **`MATCH`** — The registry confirmed the identity and every checked field matched. ```json 200 OK — MATCH theme={null} { "request_id": "req_01H…", "status": "Approved", "issuing_state": "CAN", "match_type": "full_match", "validations": [ { "outcome_code": "MATCH", "service_id": "can_residential", "service_name": "Canada Residential", "source_data": { "address": "123 Sample Street", "date_of_birth": "1990-01-01", "first_name": "John", "last_name": "Doe" }, "validation": { "address": "full_match", "full_name": "full_match" } } ] } ``` **`PARTIAL_MATCH`** — The identification number was found but one or more personal fields (usually name or date of birth) did not fully match. ```json 200 OK — PARTIAL_MATCH theme={null} { "request_id": "req_01H…", "status": "In Review", "issuing_state": "CAN", "match_type": "partial_match", "validations": [ { "outcome_code": "PARTIAL_MATCH", "service_id": "can_residential", "service_name": "Canada Residential", "source_data": { "address": "123 Sample Street", "date_of_birth": "1990-01-01", "first_name": "John", "last_name": "Doe" }, "validation": { "address": "full_match", "full_name": "no_match" } } ] } ``` **`NO_MATCH`** — The registry returned no match for the submitted data. ```json 200 OK — NO_MATCH theme={null} { "request_id": "req_01H…", "status": "Declined", "issuing_state": "CAN", "match_type": "no_match", "validations": [ { "outcome_code": "NO_MATCH", "service_id": "can_residential", "service_name": "Canada Residential", "source_data": { "address": "NO_MATCH", "full_name": "NO_MATCH" }, "validation": { "address": "no_match", "full_name": "no_match" } } ] } ``` ## Returned data The exact fields surfaced in `source_data` depend on what the registry returns. The generated example for `can_residential` currently documents this normalized shape: * `address` * `date_of_birth` * `first_name` * `last_name` ## Pricing & SLAs Canada Residential queries are billed only when Didit receives a conclusive result from the validation source. * **Per-call price:** \$0.25 USD. * **Billing:** per successful query. You are not charged when the registry is unreachable, when required fields are missing, or when the request is rejected before reaching the source. * **Latency:** typical p95 \< 2 s. * **Availability:** 99.9% per quarter on Didit's side; downstream source availability varies by country and dataset. ## Continue reading * [Canada Database Validation overview](/api-reference/database-validation/canada) * [Database Validation overview](/core-technology/database-validation/overview) * [Outcome Codes](/core-technology/database-validation/database-validation-outcome-codes) # Chile - RUT verification Source: https://docs.didit.me/api-reference/database-validation/chile/rut POST /v3/database-validation/ Verifies Chilean RUT against the Servicio de Registro Civil records. Authoritative real-time identity lookup for Chile. Real-time lookup, pay-per-call.
Verifies Chilean RUT against the Servicio de Registro Civil records. Didit exposes this service through `POST /v3/database-validation/` so you can verify the submitted data against the authoritative source and receive normalized match results. ## Coverage * **Coverage:** — * **Country:** Chile * **Service ID:** `chl_rut` * **Data domain:** Identity * **Category:** NationalIDRegistry ## Inputs | Field | Required | Example | | ----------------- | -------: | ------------------ | | `personal_number` | Yes | `SAMPLE-PER-12345` | | `first_name` | No | `John` | | `last_name` | No | `Doe` | | `date_of_birth` | No | `1990-01-01` | | `vendor_data` | No | `user-1234` | * **Required inputs:** `personal_number` * **Optional inputs:** `first_name`, `last_name`, `date_of_birth`, `vendor_data` * **Consent:** Not required * **Workflow availability:** Available in workflow * **Coverage:** — * **Price:** \$0.20 per successful query ## Body parameters ISO 3166-1 alpha-3 country code for this database service. Example: `CHL` Array containing this service ID. Pinning the service keeps the request scoped to this exact database. Example: `chl_rut` Country-specific personal identity number. Example: `SAMPLE-PER-12345` Given name to validate. Example: `John` Family name to validate. Example: `Doe` Date of birth in `YYYY-MM-DD` format. Example: `1990-01-01` Your stable user reference for this person, such as your internal user ID. Didit uses it to link standalone checks to the same end user and reduce duplicate-detection noise. Example: `user-1234` ## Input rules & validation notes * Chilean RUT (e.g. 12345678-9) * `personal_number` must be 8-12 characters long. ## How to call it ```bash cURL theme={null} curl -X POST "https://verification.didit.me/v3/database-validation/" \ -H "x-api-key: YOUR_API_KEY" \ -F "issuing_state=CHL" \ -F "services=chl_rut" \ -F "vendor_data=user-1234" \ -F "personal_number=SAMPLE-PER-12345" ``` Every successful call returns HTTP `200`. The **`outcome_code`** field tells you what actually happened — distinguishing, for example, a real biometric mismatch (`BIOMETRIC_NO_MATCH`) from a selfie that could not be read (`BIOMETRIC_IMAGE_UNUSABLE`). The `status` shown is the default feature status; your configured [Partial Match / No Match actions](/core-technology/database-validation/database-validation-warnings) can override it. **`MATCH`** — The registry confirmed the identity and every checked field matched. ```json 200 OK — MATCH theme={null} { "request_id": "req_01H…", "status": "Approved", "issuing_state": "CHL", "match_type": "full_match", "validations": [ { "outcome_code": "MATCH", "service_id": "chl_rut", "service_name": "Chile - RUT verification", "source_data": { "date_of_birth": "1990-01-01", "first_name": "John", "gender": "M", "identification_number": "SAMPLE-ID-12345", "last_name": "Doe" }, "validation": { "identification_number": "full_match" } } ] } ``` **`NO_MATCH`** — The registry returned no match for the submitted data. ```json 200 OK — NO_MATCH theme={null} { "request_id": "req_01H…", "status": "Declined", "issuing_state": "CHL", "match_type": "no_match", "validations": [ { "outcome_code": "NO_MATCH", "service_id": "chl_rut", "service_name": "Chile - RUT verification", "source_data": { "identification_number": "NO_MATCH" }, "validation": { "identification_number": "no_match" } } ] } ``` ## Returned data The exact fields surfaced in `source_data` depend on what the registry returns. The generated example for `chl_rut` currently documents this normalized shape: * `date_of_birth` * `first_name` * `gender` * `identification_number` * `last_name` ## Pricing & SLAs Chile - RUT verification queries are billed only when Didit receives a conclusive result from the validation source. * **Per-call price:** \$0.20 USD. * **Billing:** per successful query. You are not charged when the registry is unreachable, when required fields are missing, or when the request is rejected before reaching the source. * **Latency:** typical p95 \< 2 s. * **Availability:** 99.9% per quarter on Didit's side; downstream source availability varies by country and dataset. ## Continue reading * [Chile Database Validation overview](/api-reference/database-validation/chile) * [Database Validation overview](/core-technology/database-validation/overview) * [Outcome Codes](/core-technology/database-validation/database-validation-outcome-codes) # China Bank Card Source: https://docs.didit.me/api-reference/database-validation/china/bank-card POST /v3/database-validation/ Verifies input data against the official data service in China. Authoritative real-time identity lookup for China. Real-time lookup, pay-per-call.
Verifies input data against the official data service in China. Didit exposes this service through `POST /v3/database-validation/` so you can verify the submitted data against the authoritative source and receive normalized match results. ## Coverage * **Coverage:** \~ 100% * **Country:** China * **Service ID:** `chn_bank_card` * **Data domain:** Financial * **Category:** Banking ## Inputs | Field | Required | Example | | ------------------ | -------: | -------------------- | | `full_name` | Yes | `王新伟` | | `date_of_birth` | Yes | `1990-01-01` | | `national_id` | Yes | `11010519900101003X` | | `bank_card_number` | Yes | `4111111111111111` | | `vendor_data` | No | `user-1234` | * **Required inputs:** `full_name`, `date_of_birth`, `national_id`, `bank_card_number` * **Optional inputs:** `vendor_data` * **Consent:** Required * **Workflow availability:** Available in workflow with field mapping * **Coverage:** \~ 100% * **Price:** \$0.40 per successful query In a workflow, `bank_card_number` is not printed on an identity document, so no step produces it on its own. Collect it from a Questionnaire answer, a Document AI extraction field, or a value you send when you create the session, and map it on the Database Validation step. Until it is mapped the workflow editor shows this service disabled and names the missing input; at run time a missing input means the check is skipped before any query, so you are never billed for a database that could not be asked. ## Body parameters ISO 3166-1 alpha-3 country code for this database service. Example: `CHN` Array containing this service ID. Pinning the service keeps the request scoped to this exact database. Example: `chn_bank_card` Explicit end-user consent for this service. Example: `true` Full legal name to validate. Example: `王新伟` Date of birth in `YYYY-MM-DD` format. Example: `1990-01-01` National identity number for this service. Example: `11010519900101003X` Bank card number. Example: `4111111111111111` Your stable user reference for this person, such as your internal user ID. Didit uses it to link standalone checks to the same end user and reduce duplicate-detection noise. Example: `user-1234` ## Input rules & validation notes * Date of birth must match the birth date encoded in the Chinese national ID (digits 7-14 of an 18-character number, 7-12 of a legacy 15-digit one) * `date_of_birth` must match the birth date encoded in `national_id`; the source rejects the request outright when the two disagree, so a mismatch is refused before the lookup and is not charged. * Chinese resident identity card number (15 digits or 18 characters with checksum) * `national_id` must match `(?:\d{15}|\d{17}[\dXx])`. * The final Chinese Resident Identity Card check character is validated. * `full_name` must be the original Chinese-script name as it appears in the registry or on the document. Do not send the Latin transliteration for China database checks. ## How to call it ```bash cURL theme={null} curl -X POST "https://verification.didit.me/v3/database-validation/" \ -H "x-api-key: YOUR_API_KEY" \ -F "issuing_state=CHN" \ -F "services=chn_bank_card" \ -F "vendor_data=user-1234" \ -F "consent=true" \ -F "full_name=王新伟" \ -F "date_of_birth=1990-01-01" \ -F "national_id=11010519900101003X" \ -F "bank_card_number=4111111111111111" ``` Every successful call returns HTTP `200`. The **`outcome_code`** field tells you what actually happened — distinguishing, for example, a real biometric mismatch (`BIOMETRIC_NO_MATCH`) from a selfie that could not be read (`BIOMETRIC_IMAGE_UNUSABLE`). The `status` shown is the default feature status; your configured [Partial Match / No Match actions](/core-technology/database-validation/database-validation-warnings) can override it. **`MATCH`** — The registry confirmed the identity and every checked field matched. ```json 200 OK — MATCH theme={null} { "request_id": "req_01H…", "status": "Approved", "issuing_state": "CHN", "match_type": "full_match", "validations": [ { "outcome_code": "MATCH", "service_id": "chn_bank_card", "service_name": "China Bank Card", "source_data": { "date_of_birth": "1990-01-01", "full_name": "王新伟", "identification_number": "11010519900101003X" }, "validation": { "date_of_birth": "full_match", "full_name": "full_match", "identification_number": "full_match" } } ] } ``` **`PARTIAL_MATCH`** — The identification number was found but one or more personal fields (usually name or date of birth) did not fully match. ```json 200 OK — PARTIAL_MATCH theme={null} { "request_id": "req_01H…", "status": "In Review", "issuing_state": "CHN", "match_type": "partial_match", "validations": [ { "outcome_code": "PARTIAL_MATCH", "service_id": "chn_bank_card", "service_name": "China Bank Card", "source_data": { "date_of_birth": "1990-01-01", "full_name": "王新伟", "identification_number": "11010519900101003X" }, "validation": { "date_of_birth": "full_match", "full_name": "no_match", "identification_number": "full_match" } } ] } ``` **`NO_MATCH`** — The registry returned no match for the submitted data. ```json 200 OK — NO_MATCH theme={null} { "request_id": "req_01H…", "status": "Declined", "issuing_state": "CHN", "match_type": "no_match", "validations": [ { "outcome_code": "NO_MATCH", "service_id": "chn_bank_card", "service_name": "China Bank Card", "source_data": { "date_of_birth": "NO_MATCH", "full_name": "NO_MATCH", "identification_number": "NO_MATCH" }, "validation": { "date_of_birth": "no_match", "full_name": "no_match", "identification_number": "no_match" } } ] } ``` ## Returned data The exact fields surfaced in `source_data` depend on what the registry returns. The generated example for `chn_bank_card` currently documents this normalized shape: * `date_of_birth` * `full_name` * `identification_number` ## Pricing & SLAs China Bank Card queries are billed only when Didit receives a conclusive result from the validation source. * **Per-call price:** \$0.40 USD. * **Billing:** per successful query. You are not charged when the registry is unreachable, when required fields are missing, or when the request is rejected before reaching the source. * **Latency:** typical p95 \< 2 s. * **Availability:** 99.9% per quarter on Didit's side; downstream source availability varies by country and dataset. ## Continue reading * [China Database Validation overview](/api-reference/database-validation/china) * [Database Validation overview](/core-technology/database-validation/overview) * [Outcome Codes](/core-technology/database-validation/database-validation-outcome-codes) # China National ID Source: https://docs.didit.me/api-reference/database-validation/china/national-id POST /v3/database-validation/ Verifies input data against the official data service in China. Authoritative real-time identity lookup for China. Real-time lookup, pay-per-call.
Verifies input data against the official data service in China. Didit exposes this service through `POST /v3/database-validation/` so you can verify the submitted data against the authoritative source and receive normalized match results. ## Coverage * **Coverage:** \~ 100% * **Country:** China * **Service ID:** `chn_national_id` * **Data domain:** Identity * **Category:** NationalIDRegistry ## Inputs | Field | Required | Example | | --------------- | -------: | -------------------- | | `full_name` | Yes | `王新伟` | | `date_of_birth` | Yes | `1990-01-01` | | `national_id` | Yes | `11010519900101003X` | | `vendor_data` | No | `user-1234` | * **Required inputs:** `full_name`, `date_of_birth`, `national_id` * **Optional inputs:** `vendor_data` * **Consent:** Required * **Workflow availability:** Available in workflow * **Coverage:** \~ 100% * **Price:** \$0.30 per successful query Not every document this service accepts carries the identifier it queries by. When the identifier is not extracted from the document the check is recorded as **not applicable** - no database is queried and you are not charged - which for some countries is a large share of real users. To cover them, also collect the identifier from a Questionnaire answer, a Document AI extraction field, or a value you send when you create the session, and map it on the Database Validation step. ## Body parameters ISO 3166-1 alpha-3 country code for this database service. Example: `CHN` Array containing this service ID. Pinning the service keeps the request scoped to this exact database. Example: `chn_national_id` Explicit end-user consent for this service. Example: `true` Full legal name to validate. Example: `王新伟` Date of birth in `YYYY-MM-DD` format. Example: `1990-01-01` National identity number for this service. Example: `11010519900101003X` Your stable user reference for this person, such as your internal user ID. Didit uses it to link standalone checks to the same end user and reduce duplicate-detection noise. Example: `user-1234` ## Input rules & validation notes * Date of birth must match the birth date encoded in the Chinese national ID (digits 7-14 of an 18-character number, 7-12 of a legacy 15-digit one) * `date_of_birth` must match the birth date encoded in `national_id`; the source rejects the request outright when the two disagree, so a mismatch is refused before the lookup and is not charged. * `national_id` must match `(\d{15}|\d{17}[\dXx])`. * The final Chinese Resident Identity Card check character is validated. * `full_name` must be the original Chinese-script name as it appears in the registry or on the document. Do not send the Latin transliteration for China database checks. ## How to call it ```bash cURL theme={null} curl -X POST "https://verification.didit.me/v3/database-validation/" \ -H "x-api-key: YOUR_API_KEY" \ -F "issuing_state=CHN" \ -F "services=chn_national_id" \ -F "vendor_data=user-1234" \ -F "consent=true" \ -F "full_name=王新伟" \ -F "date_of_birth=1990-01-01" \ -F "national_id=11010519900101003X" ``` Every successful call returns HTTP `200`. The **`outcome_code`** field tells you what actually happened — distinguishing, for example, a real biometric mismatch (`BIOMETRIC_NO_MATCH`) from a selfie that could not be read (`BIOMETRIC_IMAGE_UNUSABLE`). The `status` shown is the default feature status; your configured [Partial Match / No Match actions](/core-technology/database-validation/database-validation-warnings) can override it. **`MATCH`** — The registry confirmed the identity and every checked field matched. ```json 200 OK — MATCH theme={null} { "request_id": "req_01H…", "status": "Approved", "issuing_state": "CHN", "match_type": "full_match", "validations": [ { "outcome_code": "MATCH", "service_id": "chn_national_id", "service_name": "China National ID", "source_data": { "date_of_birth": "1990-01-01", "identification_number": "11010519900101003X", "verifications": { "date_of_birth": true, "full_name": true, "identification_number": true } }, "validation": { "date_of_birth": "full_match", "full_name": "full_match", "identification_number": "full_match" } } ] } ``` **`PARTIAL_MATCH`** — The identification number was found but one or more personal fields (usually name or date of birth) did not fully match. ```json 200 OK — PARTIAL_MATCH theme={null} { "request_id": "req_01H…", "status": "In Review", "issuing_state": "CHN", "match_type": "partial_match", "validations": [ { "outcome_code": "PARTIAL_MATCH", "service_id": "chn_national_id", "service_name": "China National ID", "source_data": { "date_of_birth": "1990-01-01", "identification_number": "11010519900101003X", "verifications": { "date_of_birth": true, "full_name": false, "identification_number": true } }, "validation": { "date_of_birth": "full_match", "full_name": "no_match", "identification_number": "full_match" } } ] } ``` **`NO_MATCH`** — The registry returned no match for the submitted data. ```json 200 OK — NO_MATCH theme={null} { "request_id": "req_01H…", "status": "Declined", "issuing_state": "CHN", "match_type": "no_match", "validations": [ { "outcome_code": "NO_MATCH", "service_id": "chn_national_id", "service_name": "China National ID", "source_data": { "date_of_birth": "NO_MATCH", "full_name": "NO_MATCH", "identification_number": "NO_MATCH" }, "validation": { "date_of_birth": "no_match", "full_name": "no_match", "identification_number": "no_match" } } ] } ``` ## Returned data The exact fields surfaced in `source_data` depend on what the registry returns. The generated example for `chn_national_id` currently documents this normalized shape: * `date_of_birth` * `identification_number` ## Pricing & SLAs China National ID queries are billed only when Didit receives a conclusive result from the validation source. * **Per-call price:** \$0.30 USD. * **Billing:** per successful query. You are not charged when the registry is unreachable, when required fields are missing, or when the request is rejected before reaching the source. * **Latency:** typical p95 \< 2 s. * **Availability:** 99.9% per quarter on Didit's side; downstream source availability varies by country and dataset. ## Continue reading * [China Database Validation overview](/api-reference/database-validation/china) * [Database Validation overview](/core-technology/database-validation/overview) * [Outcome Codes](/core-technology/database-validation/database-validation-outcome-codes) # China Passport Verification Source: https://docs.didit.me/api-reference/database-validation/china/passport-verification POST /v3/database-validation/ Verifies input data against the official data service in China. Authoritative real-time identity lookup for China. Real-time lookup, pay-per-call.
Verifies input data against the official data service in China. Didit exposes this service through `POST /v3/database-validation/` so you can verify the submitted data against the authoritative source and receive normalized match results. ## Coverage * **Coverage:** \~ 100% * **Country:** China * **Service ID:** `chn_passport_verification` * **Data domain:** Document * **Category:** Passport ## Inputs | Field | Required | Example | | ----------------- | -------: | -------------------- | | `full_name` | Yes | `王新伟` | | `date_of_birth` | Yes | `1990-01-01` | | `national_id` | Yes | `11010519900101003X` | | `passport_number` | Yes | `SAMPLE-PASS-12345` | | `vendor_data` | No | `user-1234` | * **Required inputs:** `full_name`, `date_of_birth`, `national_id`, `passport_number` * **Optional inputs:** `vendor_data` * **Consent:** Required * **Workflow availability:** Available in workflow * **Coverage:** \~ 100% * **Price:** \$1.00 per successful query Not every document this service accepts carries the identifier it queries by. When the identifier is not extracted from the document the check is recorded as **not applicable** - no database is queried and you are not charged - which for some countries is a large share of real users. To cover them, also collect the identifier from a Questionnaire answer, a Document AI extraction field, or a value you send when you create the session, and map it on the Database Validation step. ## Body parameters ISO 3166-1 alpha-3 country code for this database service. Example: `CHN` Array containing this service ID. Pinning the service keeps the request scoped to this exact database. Example: `chn_passport_verification` Explicit end-user consent for this service. Example: `true` Full legal name to validate. Example: `王新伟` Date of birth in `YYYY-MM-DD` format. Example: `1990-01-01` National identity number for this service. Example: `11010519900101003X` Passport number. Example: `SAMPLE-PASS-12345` Your stable user reference for this person, such as your internal user ID. Didit uses it to link standalone checks to the same end user and reduce duplicate-detection noise. Example: `user-1234` ## Input rules & validation notes * Date of birth must match the birth date encoded in the Chinese national ID (digits 7-14 of an 18-character number, 7-12 of a legacy 15-digit one) * `date_of_birth` must match the birth date encoded in `national_id`; the source rejects the request outright when the two disagree, so a mismatch is refused before the lookup and is not charged. * `national_id` must match `(?:\d{15}|\d{17}[\dXx])`. * The final Chinese Resident Identity Card check character is validated. * `full_name` must be the original Chinese-script name as it appears in the registry or on the document. Do not send the Latin transliteration for China database checks. ## How to call it ```bash cURL theme={null} curl -X POST "https://verification.didit.me/v3/database-validation/" \ -H "x-api-key: YOUR_API_KEY" \ -F "issuing_state=CHN" \ -F "services=chn_passport_verification" \ -F "vendor_data=user-1234" \ -F "consent=true" \ -F "full_name=王新伟" \ -F "date_of_birth=1990-01-01" \ -F "national_id=11010519900101003X" \ -F "passport_number=SAMPLE-PASS-12345" ``` Every successful call returns HTTP `200`. The **`outcome_code`** field tells you what actually happened — distinguishing, for example, a real biometric mismatch (`BIOMETRIC_NO_MATCH`) from a selfie that could not be read (`BIOMETRIC_IMAGE_UNUSABLE`). The `status` shown is the default feature status; your configured [Partial Match / No Match actions](/core-technology/database-validation/database-validation-warnings) can override it. **`MATCH`** — The registry confirmed the identity and every checked field matched. ```json 200 OK — MATCH theme={null} { "request_id": "req_01H…", "status": "Approved", "issuing_state": "CHN", "match_type": "full_match", "validations": [ { "outcome_code": "MATCH", "service_id": "chn_passport_verification", "service_name": "China Passport Verification", "source_data": { "date_of_birth": "1990-01-01", "identification_number": "11010519900101003X", "verifications": { "date_of_birth": true, "full_name": true, "identification_number": true } }, "validation": { "date_of_birth": "full_match", "full_name": "full_match", "identification_number": "full_match" } } ] } ``` **`PARTIAL_MATCH`** — The identification number was found but one or more personal fields (usually name or date of birth) did not fully match. ```json 200 OK — PARTIAL_MATCH theme={null} { "request_id": "req_01H…", "status": "In Review", "issuing_state": "CHN", "match_type": "partial_match", "validations": [ { "outcome_code": "PARTIAL_MATCH", "service_id": "chn_passport_verification", "service_name": "China Passport Verification", "source_data": { "date_of_birth": "1990-01-01", "identification_number": "11010519900101003X", "verifications": { "date_of_birth": true, "full_name": false, "identification_number": true } }, "validation": { "date_of_birth": "full_match", "full_name": "no_match", "identification_number": "full_match" } } ] } ``` **`NO_MATCH`** — The registry returned no match for the submitted data. ```json 200 OK — NO_MATCH theme={null} { "request_id": "req_01H…", "status": "Declined", "issuing_state": "CHN", "match_type": "no_match", "validations": [ { "outcome_code": "NO_MATCH", "service_id": "chn_passport_verification", "service_name": "China Passport Verification", "source_data": { "date_of_birth": "NO_MATCH", "full_name": "NO_MATCH", "identification_number": "NO_MATCH" }, "validation": { "date_of_birth": "no_match", "full_name": "no_match", "identification_number": "no_match" } } ] } ``` ## Returned data The exact fields surfaced in `source_data` depend on what the registry returns. The generated example for `chn_passport_verification` currently documents this normalized shape: * `date_of_birth` * `identification_number` ## Pricing & SLAs China Passport Verification queries are billed only when Didit receives a conclusive result from the validation source. * **Per-call price:** \$1.00 USD. * **Billing:** per successful query. You are not charged when the registry is unreachable, when required fields are missing, or when the request is rejected before reaching the source. * **Latency:** typical p95 \< 2 s. * **Availability:** 99.9% per quarter on Didit's side; downstream source availability varies by country and dataset. ## Continue reading * [China Database Validation overview](/api-reference/database-validation/china) * [Database Validation overview](/core-technology/database-validation/overview) * [Outcome Codes](/core-technology/database-validation/database-validation-outcome-codes) # China Phone Source: https://docs.didit.me/api-reference/database-validation/china/phone POST /v3/database-validation/ Verifies input data against the official data service in China. Authoritative real-time identity lookup for China. Real-time lookup, pay-per-call.
Verifies input data against the official data service in China. Didit exposes this service through `POST /v3/database-validation/` so you can verify the submitted data against the authoritative source and receive normalized match results. ## Coverage * **Coverage:** \~ 100% * **Country:** China * **Service ID:** `chn_phone` * **Data domain:** Telecom * **Category:** Telecom ## Inputs | Field | Required | Example | | --------------- | -------: | -------------------- | | `full_name` | Yes | `王新伟` | | `date_of_birth` | Yes | `1990-01-01` | | `national_id` | Yes | `11010519900101003X` | | `phone` | Yes | `+15550101000` | | `vendor_data` | No | `user-1234` | * **Required inputs:** `full_name`, `date_of_birth`, `national_id`, `phone` * **Optional inputs:** `vendor_data` * **Consent:** Required * **Workflow availability:** Available in workflow * **Coverage:** \~ 100% * **Price:** \$0.30 per successful query ## Body parameters ISO 3166-1 alpha-3 country code for this database service. Example: `CHN` Array containing this service ID. Pinning the service keeps the request scoped to this exact database. Example: `chn_phone` Explicit end-user consent for this service. Example: `true` Full legal name to validate. Example: `王新伟` Date of birth in `YYYY-MM-DD` format. Example: `1990-01-01` National identity number for this service. Example: `11010519900101003X` Phone number in international format. Example: `+15550101000` Your stable user reference for this person, such as your internal user ID. Didit uses it to link standalone checks to the same end user and reduce duplicate-detection noise. Example: `user-1234` ## Input rules & validation notes * Date of birth must match the birth date encoded in the Chinese national ID (digits 7-14 of an 18-character number, 7-12 of a legacy 15-digit one) * `date_of_birth` must match the birth date encoded in `national_id`; the source rejects the request outright when the two disagree, so a mismatch is refused before the lookup and is not charged. * Chinese resident identity card number (15 digits or 18 characters with checksum) * `national_id` must match `(?:\d{15}|\d{17}[\dXx])`. * The final Chinese Resident Identity Card check character is validated. * `full_name` must be the original Chinese-script name as it appears in the registry or on the document. Do not send the Latin transliteration for China database checks. ## How to call it ```bash cURL theme={null} curl -X POST "https://verification.didit.me/v3/database-validation/" \ -H "x-api-key: YOUR_API_KEY" \ -F "issuing_state=CHN" \ -F "services=chn_phone" \ -F "vendor_data=user-1234" \ -F "consent=true" \ -F "full_name=王新伟" \ -F "date_of_birth=1990-01-01" \ -F "national_id=11010519900101003X" \ -F "phone=+15550101000" ``` Every successful call returns HTTP `200`. The **`outcome_code`** field tells you what actually happened — distinguishing, for example, a real biometric mismatch (`BIOMETRIC_NO_MATCH`) from a selfie that could not be read (`BIOMETRIC_IMAGE_UNUSABLE`). The `status` shown is the default feature status; your configured [Partial Match / No Match actions](/core-technology/database-validation/database-validation-warnings) can override it. **`MATCH`** — The registry confirmed the identity and every checked field matched. ```json 200 OK — MATCH theme={null} { "request_id": "req_01H…", "status": "Approved", "issuing_state": "CHN", "match_type": "full_match", "validations": [ { "outcome_code": "MATCH", "service_id": "chn_phone", "service_name": "China Phone", "source_data": { "date_of_birth": "1990-01-01", "full_name": "王新伟", "identification_number": "11010519900101003X" }, "validation": { "date_of_birth": "full_match", "full_name": "full_match", "identification_number": "full_match" } } ] } ``` **`PARTIAL_MATCH`** — The identification number was found but one or more personal fields (usually name or date of birth) did not fully match. ```json 200 OK — PARTIAL_MATCH theme={null} { "request_id": "req_01H…", "status": "In Review", "issuing_state": "CHN", "match_type": "partial_match", "validations": [ { "outcome_code": "PARTIAL_MATCH", "service_id": "chn_phone", "service_name": "China Phone", "source_data": { "date_of_birth": "1990-01-01", "full_name": "王新伟", "identification_number": "11010519900101003X" }, "validation": { "date_of_birth": "full_match", "full_name": "no_match", "identification_number": "full_match" } } ] } ``` **`NO_MATCH`** — The registry returned no match for the submitted data. ```json 200 OK — NO_MATCH theme={null} { "request_id": "req_01H…", "status": "Declined", "issuing_state": "CHN", "match_type": "no_match", "validations": [ { "outcome_code": "NO_MATCH", "service_id": "chn_phone", "service_name": "China Phone", "source_data": { "date_of_birth": "NO_MATCH", "full_name": "NO_MATCH", "identification_number": "NO_MATCH" }, "validation": { "date_of_birth": "no_match", "full_name": "no_match", "identification_number": "no_match" } } ] } ``` ## Returned data The exact fields surfaced in `source_data` depend on what the registry returns. The generated example for `chn_phone` currently documents this normalized shape: * `date_of_birth` * `full_name` * `identification_number` ## Pricing & SLAs China Phone queries are billed only when Didit receives a conclusive result from the validation source. * **Per-call price:** \$0.30 USD. * **Billing:** per successful query. You are not charged when the registry is unreachable, when required fields are missing, or when the request is rejected before reaching the source. * **Latency:** typical p95 \< 2 s. * **Availability:** 99.9% per quarter on Didit's side; downstream source availability varies by country and dataset. ## Continue reading * [China Database Validation overview](/api-reference/database-validation/china) * [Database Validation overview](/core-technology/database-validation/overview) * [Outcome Codes](/core-technology/database-validation/database-validation-outcome-codes) # Colombia - Cédula verification Source: https://docs.didit.me/api-reference/database-validation/colombia/cedula POST /v3/database-validation/ Verifies Colombian citizen identity data against Registraduría General de la Nación / ANI government records. Authoritative real-time identity lookup for Colombia. Real-time lookup, pay-per-call.
Verifies Colombian citizen identity data against Registraduría General de la Nación / ANI government records. Didit exposes this service through `POST /v3/database-validation/` so you can verify the submitted data against the authoritative source and receive normalized match results. ## Coverage * **Coverage:** 90-95% * **Country:** Colombia * **Service ID:** `col_cedula` * **Data domain:** Identity * **Category:** NationalIDRegistry ## Inputs | Field | Required | Example | | ----------------- | -------: | ------------ | | `personal_number` | Yes | `111111` | | `date_of_issue` | Yes | `1990-01-01` | | `first_name` | No | `John` | | `last_name` | No | `Doe` | | `vendor_data` | No | `user-1234` | * **Required inputs:** `personal_number`, `date_of_issue` * **Optional inputs:** `first_name`, `last_name`, `vendor_data` * **Consent:** Not required * **Workflow availability:** Available in workflow * **Coverage:** 90-95% * **Price:** \$0.20 per successful query ## Body parameters ISO 3166-1 alpha-3 country code for this database service. Example: `COL` Array containing this service ID. Pinning the service keeps the request scoped to this exact database. Example: `col_cedula` Country-specific personal identity number. Example: `111111` `date_of_issue` value required by this database service. Example: `1990-01-01` Given name to validate. Example: `John` Family name to validate. Example: `Doe` Your stable user reference for this person, such as your internal user ID. Didit uses it to link standalone checks to the same end user and reduce duplicate-detection noise. Example: `user-1234` ## Input rules & validation notes * Colombian Cédula (6-10 digits) * `personal_number` must contain digits only; remove spaces, hyphens, and punctuation before sending the request. * `personal_number` must be 6-10 characters long. ## How to call it ```bash cURL theme={null} curl -X POST "https://verification.didit.me/v3/database-validation/" \ -H "x-api-key: YOUR_API_KEY" \ -F "issuing_state=COL" \ -F "services=col_cedula" \ -F "vendor_data=user-1234" \ -F "personal_number=111111" \ -F "date_of_issue=1990-01-01" ``` Every successful call returns HTTP `200`. The **`outcome_code`** field tells you what actually happened — distinguishing, for example, a real biometric mismatch (`BIOMETRIC_NO_MATCH`) from a selfie that could not be read (`BIOMETRIC_IMAGE_UNUSABLE`). The `status` shown is the default feature status; your configured [Partial Match / No Match actions](/core-technology/database-validation/database-validation-warnings) can override it. **`MATCH`** — The registry confirmed the identity and every checked field matched. ```json 200 OK — MATCH theme={null} { "request_id": "req_01H…", "status": "Approved", "issuing_state": "COL", "match_type": "full_match", "validations": [ { "outcome_code": "MATCH", "service_id": "col_cedula", "service_name": "Colombia - Cédula verification", "source_data": { "cedula_status": "sample_value", "first_name": "John", "identification_number": "SAMPLE-ID-12345", "last_name": "Doe", "verifications": { "identification_number": true } }, "validation": { "identification_number": "full_match" } } ] } ``` **`NO_MATCH`** — The registry returned no match for the submitted data. ```json 200 OK — NO_MATCH theme={null} { "request_id": "req_01H…", "status": "Declined", "issuing_state": "COL", "match_type": "no_match", "validations": [ { "outcome_code": "NO_MATCH", "service_id": "col_cedula", "service_name": "Colombia - Cédula verification", "source_data": { "identification_number": "NO_MATCH" }, "validation": { "identification_number": "no_match" } } ] } ``` ## Returned data The exact fields surfaced in `source_data` depend on what the registry returns. The generated example for `col_cedula` currently documents this normalized shape: * `cedula_status` * `first_name` * `identification_number` * `last_name` ## Pricing & SLAs Colombia - Cédula verification queries are billed only when Didit receives a conclusive result from the validation source. * **Per-call price:** \$0.20 USD. * **Billing:** per successful query. You are not charged when the registry is unreachable, when required fields are missing, or when the request is rejected before reaching the source. * **Latency:** typical p95 \< 2 s. * **Availability:** 99.9% per quarter on Didit's side; downstream source availability varies by country and dataset. ## Continue reading * [Colombia Database Validation overview](/api-reference/database-validation/colombia) * [Database Validation overview](/core-technology/database-validation/overview) * [Outcome Codes](/core-technology/database-validation/database-validation-outcome-codes) # Colombia - Migración Colombia foreigner status Source: https://docs.didit.me/api-reference/database-validation/colombia/migracion POST /v3/database-validation/ Verifies a foreigner's migratory status and identity against Migración Colombia government records (cédula de extranjería). Authoritative real-time identity lookup for Colombia. Real-time lookup, pay-per-call.
Verifies a foreigner's migratory status and identity against Migración Colombia government records (cédula de extranjería). Didit exposes this service through `POST /v3/database-validation/` so you can verify the submitted data against the authoritative source and receive normalized match results. ## Coverage * **Coverage:** — * **Country:** Colombia * **Service ID:** `col_migracion` * **Data domain:** Identity * **Category:** ResidencePermit ## Inputs | Field | Required | Example | | ----------------- | -------: | ------------ | | `personal_number` | Yes | `111111` | | `date_of_birth` | Yes | `1990-01-01` | | `nationality` | Yes | `MEX` | | `first_name` | No | `John` | | `last_name` | No | `Doe` | | `vendor_data` | No | `user-1234` | * **Required inputs:** `personal_number`, `date_of_birth`, `nationality` * **Optional inputs:** `first_name`, `last_name`, `vendor_data` * **Consent:** Not required * **Workflow availability:** Available in workflow * **Coverage:** — * **Price:** \$1.20 per successful query ## Body parameters ISO 3166-1 alpha-3 country code for this database service. Example: `COL` Array containing this service ID. Pinning the service keeps the request scoped to this exact database. Example: `col_migracion` Country-specific personal identity number. Example: `111111` Date of birth in `YYYY-MM-DD` format. Example: `1990-01-01` `nationality` value required by this database service. Example: `MEX` Given name to validate. Example: `John` Family name to validate. Example: `Doe` Your stable user reference for this person, such as your internal user ID. Didit uses it to link standalone checks to the same end user and reduce duplicate-detection noise. Example: `user-1234` ## Input rules & validation notes * Colombian Cédula (6-10 digits) * `personal_number` must contain digits only; remove spaces, hyphens, and punctuation before sending the request. * `personal_number` must be 6-10 characters long. ## How to call it ```bash cURL theme={null} curl -X POST "https://verification.didit.me/v3/database-validation/" \ -H "x-api-key: YOUR_API_KEY" \ -F "issuing_state=COL" \ -F "services=col_migracion" \ -F "vendor_data=user-1234" \ -F "personal_number=111111" \ -F "date_of_birth=1990-01-01" \ -F "nationality=MEX" ``` Every successful call returns HTTP `200`. The **`outcome_code`** field tells you what actually happened — distinguishing, for example, a real biometric mismatch (`BIOMETRIC_NO_MATCH`) from a selfie that could not be read (`BIOMETRIC_IMAGE_UNUSABLE`). The `status` shown is the default feature status; your configured [Partial Match / No Match actions](/core-technology/database-validation/database-validation-warnings) can override it. **`MATCH`** — The registry confirmed the identity and every checked field matched. ```json 200 OK — MATCH theme={null} { "request_id": "req_01H…", "status": "Approved", "issuing_state": "COL", "match_type": "full_match", "validations": [ { "outcome_code": "MATCH", "service_id": "col_migracion", "service_name": "Colombia - Migración Colombia foreigner status", "source_data": { "first_name": "John", "identification_number": "SAMPLE-ID-12345", "last_name": "Doe" }, "validation": { "date_of_birth": "full_match", "identification_number": "full_match" } } ] } ``` **`PARTIAL_MATCH`** — The identification number was found but one or more personal fields (usually name or date of birth) did not fully match. ```json 200 OK — PARTIAL_MATCH theme={null} { "request_id": "req_01H…", "status": "In Review", "issuing_state": "COL", "match_type": "partial_match", "validations": [ { "outcome_code": "PARTIAL_MATCH", "service_id": "col_migracion", "service_name": "Colombia - Migración Colombia foreigner status", "source_data": { "first_name": "John", "identification_number": "SAMPLE-ID-12345", "last_name": "Doe" }, "validation": { "date_of_birth": "no_match", "identification_number": "full_match" } } ] } ``` **`NO_MATCH`** — The registry returned no match for the submitted data. ```json 200 OK — NO_MATCH theme={null} { "request_id": "req_01H…", "status": "Declined", "issuing_state": "COL", "match_type": "no_match", "validations": [ { "outcome_code": "NO_MATCH", "service_id": "col_migracion", "service_name": "Colombia - Migración Colombia foreigner status", "source_data": { "date_of_birth": "NO_MATCH", "identification_number": "NO_MATCH" }, "validation": { "date_of_birth": "no_match", "identification_number": "no_match" } } ] } ``` ## Returned data The exact fields surfaced in `source_data` depend on what the registry returns. The generated example for `col_migracion` currently documents this normalized shape: * `first_name` * `identification_number` * `last_name` ## Pricing & SLAs Colombia - Migración Colombia foreigner status queries are billed only when Didit receives a conclusive result from the validation source. * **Per-call price:** \$1.20 USD. * **Billing:** per successful query. You are not charged when the registry is unreachable, when required fields are missing, or when the request is rejected before reaching the source. * **Latency:** typical p95 \< 2 s. * **Availability:** 99.9% per quarter on Didit's side; downstream source availability varies by country and dataset. ## Continue reading * [Colombia Database Validation overview](/api-reference/database-validation/colombia) * [Database Validation overview](/core-technology/database-validation/overview) * [Outcome Codes](/core-technology/database-validation/database-validation-outcome-codes) # Costa Rica - Cédula verification Source: https://docs.didit.me/api-reference/database-validation/costa-rica/cedula POST /v3/database-validation/ Verifies Costa Rican national identity card data against Tribunal Supremo de Elecciones government records. Authoritative real-time identity lookup for Costa Rica. Real-time lookup, pay-per-call.
Verifies Costa Rican national identity card data against Tribunal Supremo de Elecciones government records. Didit exposes this service through `POST /v3/database-validation/` so you can verify the submitted data against the authoritative source and receive normalized match results. ## Coverage * **Coverage:** 90-95% * **Country:** Costa Rica * **Service ID:** `cri_cedula` * **Data domain:** Identity * **Category:** NationalIDRegistry ## Inputs | Field | Required | Example | | ----------------- | -------: | ----------- | | `personal_number` | Yes | `111111111` | | `first_name` | No | `John` | | `last_name` | No | `Doe` | | `vendor_data` | No | `user-1234` | * **Required inputs:** `personal_number` * **Optional inputs:** `first_name`, `last_name`, `vendor_data` * **Consent:** Not required * **Workflow availability:** Available in workflow * **Coverage:** 90-95% * **Price:** \$0.20 per successful query ## Body parameters ISO 3166-1 alpha-3 country code for this database service. Example: `CRI` Array containing this service ID. Pinning the service keeps the request scoped to this exact database. Example: `cri_cedula` Country-specific personal identity number. Example: `111111111` Given name to validate. Example: `John` Family name to validate. Example: `Doe` Your stable user reference for this person, such as your internal user ID. Didit uses it to link standalone checks to the same end user and reduce duplicate-detection noise. Example: `user-1234` ## Input rules & validation notes * Costa Rican Cédula (9-12 digits) * `personal_number` must contain digits only; remove spaces, hyphens, and punctuation before sending the request. * `personal_number` must be 9-12 characters long. ## How to call it ```bash cURL theme={null} curl -X POST "https://verification.didit.me/v3/database-validation/" \ -H "x-api-key: YOUR_API_KEY" \ -F "issuing_state=CRI" \ -F "services=cri_cedula" \ -F "vendor_data=user-1234" \ -F "personal_number=111111111" ``` Every successful call returns HTTP `200`. The **`outcome_code`** field tells you what actually happened — distinguishing, for example, a real biometric mismatch (`BIOMETRIC_NO_MATCH`) from a selfie that could not be read (`BIOMETRIC_IMAGE_UNUSABLE`). The `status` shown is the default feature status; your configured [Partial Match / No Match actions](/core-technology/database-validation/database-validation-warnings) can override it. **`MATCH`** — The registry confirmed the identity and every checked field matched. ```json 200 OK — MATCH theme={null} { "request_id": "req_01H…", "status": "Approved", "issuing_state": "CRI", "match_type": "full_match", "validations": [ { "outcome_code": "MATCH", "service_id": "cri_cedula", "service_name": "Costa Rica - Cédula verification", "source_data": { "first_name": "John", "full_name": "John Doe", "identification_number": "SAMPLE-ID-12345", "last_name": "Doe" }, "validation": { "identification_number": "full_match" } } ] } ``` **`NO_MATCH`** — The registry returned no match for the submitted data. ```json 200 OK — NO_MATCH theme={null} { "request_id": "req_01H…", "status": "Declined", "issuing_state": "CRI", "match_type": "no_match", "validations": [ { "outcome_code": "NO_MATCH", "service_id": "cri_cedula", "service_name": "Costa Rica - Cédula verification", "source_data": { "identification_number": "NO_MATCH" }, "validation": { "identification_number": "no_match" } } ] } ``` **`DOCUMENT_NOT_FOUND`** — The submitted document number does not correspond to any record in the registry. ```json 200 OK — DOCUMENT_NOT_FOUND theme={null} { "request_id": "req_01H…", "status": "Declined", "issuing_state": "CRI", "match_type": "no_match", "validations": [ { "outcome_code": "DOCUMENT_NOT_FOUND", "service_id": "cri_cedula", "service_name": "Costa Rica - Cédula verification", "source_data": { "identification_number": "NO_MATCH" }, "validation": { "identification_number": "no_match" } } ] } ``` ## Returned data The exact fields surfaced in `source_data` depend on what the registry returns. The generated example for `cri_cedula` currently documents this normalized shape: * `first_name` * `full_name` * `identification_number` * `last_name` ## Pricing & SLAs Costa Rica - Cédula verification queries are billed only when Didit receives a conclusive result from the validation source. * **Per-call price:** \$0.20 USD. * **Billing:** per successful query. You are not charged when the registry is unreachable, when required fields are missing, or when the request is rejected before reaching the source. * **Latency:** typical p95 \< 2 s. * **Availability:** 99.9% per quarter on Didit's side; downstream source availability varies by country and dataset. ## Continue reading * [Costa Rica Database Validation overview](/api-reference/database-validation/costa-rica) * [Database Validation overview](/core-technology/database-validation/overview) * [Outcome Codes](/core-technology/database-validation/database-validation-outcome-codes) # Denmark Consumer 2 Source: https://docs.didit.me/api-reference/database-validation/denmark/consumer-2 POST /v3/database-validation/ Input is verified against a source comprising multiple datasets from consumer, telephone and utility records. Authoritative real-time identity lookup for Denmark. Real-time lookup, pay-per-call.
Input is verified against a source comprising multiple datasets from consumer, telephone and utility records. Didit exposes this service through `POST /v3/database-validation/` so you can verify the submitted data against the authoritative source and receive normalized match results. ## Coverage * **Coverage:** \~ 50% * **Country:** Denmark * **Service ID:** `dnk_consumer_2` * **Data domain:** Address * **Category:** Residential ## Inputs | Field | Required | Example | | --------------------- | -------: | ---------------------- | | `first_name` | Yes | `John` | | `last_name` | Yes | `Doe` | | `date_of_birth` | Yes | `1990-01-01` | | `address.street_1` | No | `123 Sample Street` | | `address.street_2` | No | `Unit 4` | | `address.city` | No | `Sample City` | | `address.region` | No | `Sample State` | | `address.postal_code` | No | `10001` | | `phone` | No | `+15550101000` | | `email` | No | `john.doe@example.com` | | `vendor_data` | No | `user-1234` | * **Required inputs:** `first_name`, `last_name`, `date_of_birth` * **Optional inputs:** `address.street_1`, `address.street_2`, `address.city`, `address.region`, `address.postal_code`, `phone`, `email`, `vendor_data` * **Consent:** Not required * **Workflow availability:** Available in workflow * **Coverage:** \~ 50% * **Price:** \$0.97 per successful query ## Body parameters ISO 3166-1 alpha-3 country code for this database service. Example: `DNK` Array containing this service ID. Pinning the service keeps the request scoped to this exact database. Example: `dnk_consumer_2` Given name to validate. Example: `John` Family name to validate. Example: `Doe` Date of birth in `YYYY-MM-DD` format. Example: `1990-01-01` Structured residential address object. Use `street_1`, `street_2`, `city`, `region`, `postal_code`, and `country`. A complete legacy address string is still accepted but not recommended. Example: `{"street_1":"123 Sample Street","street_2":"Unit 4","city":"Sample City","region":"Sample State","postal_code":"10001","country":"US"}` Phone number in international format. Example: `+15550101000` Email address. Example: `john.doe@example.com` Your stable user reference for this person, such as your internal user ID. Didit uses it to link standalone checks to the same end user and reduce duplicate-detection noise. Example: `user-1234` ## Input rules & validation notes * `address` is optional for this service. You can send one complete `address` string and Didit will split it into structured address elements when possible, or you can send the structured fields explicitly. * For address services, send structured address fields instead of a single `address` string when possible. * `address.street_1` is the street address, including street number and street type. * `address.street_2` is apartment, unit, building, floor, or extra address line. Send it only when you have it. * `address.city` is city, suburb, district, locality, or neighborhood. * `address.region` is state, province, region, or town. * `address.postal_code` is postcode or postal code. * Address-based database services require at least street address and postal code; requests rejected before source lookup are not charged. ## How to call it ```bash cURL theme={null} curl -X POST "https://verification.didit.me/v3/database-validation/" \ -H "x-api-key: YOUR_API_KEY" \ -F "issuing_state=DNK" \ -F "services=dnk_consumer_2" \ -F "vendor_data=user-1234" \ -F "first_name=John" \ -F "last_name=Doe" \ -F "date_of_birth=1990-01-01" ``` Every successful call returns HTTP `200`. The **`outcome_code`** field tells you what actually happened — distinguishing, for example, a real biometric mismatch (`BIOMETRIC_NO_MATCH`) from a selfie that could not be read (`BIOMETRIC_IMAGE_UNUSABLE`). The `status` shown is the default feature status; your configured [Partial Match / No Match actions](/core-technology/database-validation/database-validation-warnings) can override it. **`MATCH`** — The registry confirmed the identity and every checked field matched. ```json 200 OK — MATCH theme={null} { "request_id": "req_01H…", "status": "Approved", "issuing_state": "DNK", "match_type": "full_match", "validations": [ { "outcome_code": "MATCH", "service_id": "dnk_consumer_2", "service_name": "Denmark Consumer 2", "source_data": { "address": "123 Sample Street", "date_of_birth": "1990-01-01", "first_name": "John", "last_name": "Doe" }, "validation": { "date_of_birth": "full_match", "full_name": "full_match" } } ] } ``` **`PARTIAL_MATCH`** — The identification number was found but one or more personal fields (usually name or date of birth) did not fully match. ```json 200 OK — PARTIAL_MATCH theme={null} { "request_id": "req_01H…", "status": "In Review", "issuing_state": "DNK", "match_type": "partial_match", "validations": [ { "outcome_code": "PARTIAL_MATCH", "service_id": "dnk_consumer_2", "service_name": "Denmark Consumer 2", "source_data": { "address": "123 Sample Street", "date_of_birth": "1990-01-01", "first_name": "John", "last_name": "Doe" }, "validation": { "date_of_birth": "full_match", "full_name": "no_match" } } ] } ``` **`NO_MATCH`** — The registry returned no match for the submitted data. ```json 200 OK — NO_MATCH theme={null} { "request_id": "req_01H…", "status": "Declined", "issuing_state": "DNK", "match_type": "no_match", "validations": [ { "outcome_code": "NO_MATCH", "service_id": "dnk_consumer_2", "service_name": "Denmark Consumer 2", "source_data": { "date_of_birth": "NO_MATCH", "full_name": "NO_MATCH" }, "validation": { "date_of_birth": "no_match", "full_name": "no_match" } } ] } ``` ## Returned data The exact fields surfaced in `source_data` depend on what the registry returns. The generated example for `dnk_consumer_2` currently documents this normalized shape: * `address` * `date_of_birth` * `first_name` * `last_name` ## Pricing & SLAs Denmark Consumer 2 queries are billed only when Didit receives a conclusive result from the validation source. * **Per-call price:** \$0.97 USD. * **Billing:** per successful query. You are not charged when the registry is unreachable, when required fields are missing, or when the request is rejected before reaching the source. * **Latency:** typical p95 \< 2 s. * **Availability:** 99.9% per quarter on Didit's side; downstream source availability varies by country and dataset. ## Continue reading * [Denmark Database Validation overview](/api-reference/database-validation/denmark) * [Database Validation overview](/core-technology/database-validation/overview) * [Outcome Codes](/core-technology/database-validation/database-validation-outcome-codes) # Denmark National ID Source: https://docs.didit.me/api-reference/database-validation/denmark/national-id POST /v3/database-validation/ Verifies input data against the Civil Registration service. Authoritative real-time identity lookup for Denmark. Real-time lookup, pay-per-call.
Verifies input data against the Civil Registration service. Didit exposes this service through `POST /v3/database-validation/` so you can verify the submitted data against the authoritative source and receive normalized match results. ## Coverage * **Coverage:** \~ 100% * **Country:** Denmark * **Service ID:** `dnk_national_id` * **Data domain:** Identity * **Category:** NationalIDRegistry ## Inputs | Field | Required | Example | | --------------------- | -------: | ------------------- | | `first_name` | Yes | `John` | | `last_name` | Yes | `Doe` | | `date_of_birth` | Yes | `1990-01-01` | | `national_id` | Yes | `SAMPLE-NID-12345` | | `address.street_1` | No | `123 Sample Street` | | `address.street_2` | No | `Unit 4` | | `address.city` | No | `Sample City` | | `address.region` | No | `Sample State` | | `address.postal_code` | No | `10001` | | `vendor_data` | No | `user-1234` | * **Required inputs:** `first_name`, `last_name`, `date_of_birth`, `national_id` * **Optional inputs:** `address.street_1`, `address.street_2`, `address.city`, `address.region`, `address.postal_code`, `vendor_data` * **Consent:** Not required * **Workflow availability:** Available in workflow * **Coverage:** \~ 100% * **Price:** \$1.39 per successful query Not every document this service accepts carries the identifier it queries by. When the identifier is not extracted from the document the check is recorded as **not applicable** - no database is queried and you are not charged - which for some countries is a large share of real users. To cover them, also collect the identifier from a Questionnaire answer, a Document AI extraction field, or a value you send when you create the session, and map it on the Database Validation step. ## Body parameters ISO 3166-1 alpha-3 country code for this database service. Example: `DNK` Array containing this service ID. Pinning the service keeps the request scoped to this exact database. Example: `dnk_national_id` Given name to validate. Example: `John` Family name to validate. Example: `Doe` Date of birth in `YYYY-MM-DD` format. Example: `1990-01-01` National identity number for this service. Example: `SAMPLE-NID-12345` Structured residential address object. Use `street_1`, `street_2`, `city`, `region`, `postal_code`, and `country`. A complete legacy address string is still accepted but not recommended. Example: `{"street_1":"123 Sample Street","street_2":"Unit 4","city":"Sample City","region":"Sample State","postal_code":"10001","country":"US"}` Your stable user reference for this person, such as your internal user ID. Didit uses it to link standalone checks to the same end user and reduce duplicate-detection noise. Example: `user-1234` ## Input rules & validation notes * `address` is optional for this service. You can send one complete `address` string and Didit will split it into structured address elements when possible, or you can send the structured fields explicitly. * `national_id` must match `\d{6}-?\d{4}`. * For address services, send structured address fields instead of a single `address` string when possible. * `address.street_1` is the street address, including street number and street type. * `address.street_2` is apartment, unit, building, floor, or extra address line. Send it only when you have it. * `address.city` is city, suburb, district, locality, or neighborhood. * `address.region` is state, province, region, or town. * `address.postal_code` is postcode or postal code. * Address-based database services require at least street address and postal code; requests rejected before source lookup are not charged. ## How to call it ```bash cURL theme={null} curl -X POST "https://verification.didit.me/v3/database-validation/" \ -H "x-api-key: YOUR_API_KEY" \ -F "issuing_state=DNK" \ -F "services=dnk_national_id" \ -F "vendor_data=user-1234" \ -F "first_name=John" \ -F "last_name=Doe" \ -F "date_of_birth=1990-01-01" \ -F "national_id=SAMPLE-NID-12345" ``` Every successful call returns HTTP `200`. The **`outcome_code`** field tells you what actually happened — distinguishing, for example, a real biometric mismatch (`BIOMETRIC_NO_MATCH`) from a selfie that could not be read (`BIOMETRIC_IMAGE_UNUSABLE`). The `status` shown is the default feature status; your configured [Partial Match / No Match actions](/core-technology/database-validation/database-validation-warnings) can override it. **`MATCH`** — The registry confirmed the identity and every checked field matched. ```json 200 OK — MATCH theme={null} { "request_id": "req_01H…", "status": "Approved", "issuing_state": "DNK", "match_type": "full_match", "validations": [ { "outcome_code": "MATCH", "service_id": "dnk_national_id", "service_name": "Denmark National ID", "source_data": { "date_of_birth": "1990-01-01", "first_name": "John", "full_name": "John Doe", "identification_number": "SAMPLE-ID-12345", "last_name": "Doe", "name_match_score": "1.000", "verifications": { "date_of_birth": true, "full_name": true, "identification_number": true } }, "validation": { "date_of_birth": "full_match", "full_name": "full_match", "identification_number": "full_match" } } ] } ``` **`PARTIAL_MATCH`** — The identification number was found but one or more personal fields (usually name or date of birth) did not fully match. ```json 200 OK — PARTIAL_MATCH theme={null} { "request_id": "req_01H…", "status": "In Review", "issuing_state": "DNK", "match_type": "partial_match", "validations": [ { "outcome_code": "PARTIAL_MATCH", "service_id": "dnk_national_id", "service_name": "Denmark National ID", "source_data": { "date_of_birth": "1990-01-01", "first_name": "John", "full_name": "John Doe", "identification_number": "SAMPLE-ID-12345", "last_name": "Doe", "name_match_score": "1.000", "verifications": { "date_of_birth": true, "full_name": false, "identification_number": true } }, "validation": { "date_of_birth": "full_match", "full_name": "no_match", "identification_number": "full_match" } } ] } ``` **`NO_MATCH`** — The registry returned no match for the submitted data. ```json 200 OK — NO_MATCH theme={null} { "request_id": "req_01H…", "status": "Declined", "issuing_state": "DNK", "match_type": "no_match", "validations": [ { "outcome_code": "NO_MATCH", "service_id": "dnk_national_id", "service_name": "Denmark National ID", "source_data": { "date_of_birth": "NO_MATCH", "full_name": "NO_MATCH", "identification_number": "NO_MATCH" }, "validation": { "date_of_birth": "no_match", "full_name": "no_match", "identification_number": "no_match" } } ] } ``` ## Returned data The exact fields surfaced in `source_data` depend on what the registry returns. The generated example for `dnk_national_id` currently documents this normalized shape: * `date_of_birth` * `first_name` * `full_name` * `identification_number` * `last_name` * `name_match_score` ## Pricing & SLAs Denmark National ID queries are billed only when Didit receives a conclusive result from the validation source. * **Per-call price:** \$1.39 USD. * **Billing:** per successful query. You are not charged when the registry is unreachable, when required fields are missing, or when the request is rejected before reaching the source. * **Latency:** typical p95 \< 2 s. * **Availability:** 99.9% per quarter on Didit's side; downstream source availability varies by country and dataset. ## Continue reading * [Denmark Database Validation overview](/api-reference/database-validation/denmark) * [Database Validation overview](/core-technology/database-validation/overview) * [Outcome Codes](/core-technology/database-validation/database-validation-outcome-codes) # Dominican Republic - Cédula verification Source: https://docs.didit.me/api-reference/database-validation/dominican-republic/cedula POST /v3/database-validation/ Verifies Dominican Cédula directly against the Junta Central Electoral civil registry. Authoritative real-time identity lookup for Dominican Republic. Real-time lookup, pay-per-call.
Verifies Dominican Cédula directly against the Junta Central Electoral civil registry. Didit exposes this service through `POST /v3/database-validation/` so you can verify the submitted data against the authoritative source and receive normalized match results. ## Coverage * **Coverage:** — * **Country:** Dominican Republic * **Service ID:** `dom_cedula` * **Data domain:** Identity * **Category:** NationalIDRegistry ## Inputs | Field | Required | Example | | ----------------- | -------: | ------------- | | `personal_number` | Yes | `11111111111` | | `vendor_data` | No | `user-1234` | * **Required inputs:** `personal_number` * **Optional inputs:** `vendor_data` * **Consent:** Not required * **Workflow availability:** Available in workflow * **Coverage:** — * **Price:** \$0.05 per successful query ## Body parameters ISO 3166-1 alpha-3 country code for this database service. Example: `DOM` Array containing this service ID. Pinning the service keeps the request scoped to this exact database. Example: `dom_cedula` Country-specific personal identity number. Example: `11111111111` Your stable user reference for this person, such as your internal user ID. Didit uses it to link standalone checks to the same end user and reduce duplicate-detection noise. Example: `user-1234` ## Input rules & validation notes * Dominican Cédula (exactly 11 digits) * `personal_number` must contain digits only; remove spaces, hyphens, and punctuation before sending the request. * `personal_number` must be exactly 11 characters long. ## How to call it ```bash cURL theme={null} curl -X POST "https://verification.didit.me/v3/database-validation/" \ -H "x-api-key: YOUR_API_KEY" \ -F "issuing_state=DOM" \ -F "services=dom_cedula" \ -F "vendor_data=user-1234" \ -F "personal_number=11111111111" ``` Every successful call returns HTTP `200`. The **`outcome_code`** field tells you what actually happened — distinguishing, for example, a real biometric mismatch (`BIOMETRIC_NO_MATCH`) from a selfie that could not be read (`BIOMETRIC_IMAGE_UNUSABLE`). The `status` shown is the default feature status; your configured [Partial Match / No Match actions](/core-technology/database-validation/database-validation-warnings) can override it. **`MATCH`** — The registry confirmed the identity and every checked field matched. ```json 200 OK — MATCH theme={null} { "request_id": "req_01H…", "status": "Approved", "issuing_state": "DOM", "match_type": "full_match", "validations": [ { "outcome_code": "MATCH", "service_id": "dom_cedula", "service_name": "Dominican Republic - Cédula verification", "source_data": { "identification_number": "SAMPLE-ID-12345" }, "validation": { "identification_number": "full_match" } } ] } ``` **`NO_MATCH`** — The registry returned no match for the submitted data. ```json 200 OK — NO_MATCH theme={null} { "request_id": "req_01H…", "status": "Declined", "issuing_state": "DOM", "match_type": "no_match", "validations": [ { "outcome_code": "NO_MATCH", "service_id": "dom_cedula", "service_name": "Dominican Republic - Cédula verification", "source_data": { "identification_number": "NO_MATCH" }, "validation": { "identification_number": "no_match" } } ] } ``` ## Returned data The exact fields surfaced in `source_data` depend on what the registry returns. The generated example for `dom_cedula` currently documents this normalized shape: * `identification_number` ## Pricing & SLAs Dominican Republic - Cédula verification queries are billed only when Didit receives a conclusive result from the validation source. * **Per-call price:** \$0.05 USD. * **Billing:** per successful query. You are not charged when the registry is unreachable, when required fields are missing, or when the request is rejected before reaching the source. * **Latency:** typical p95 \< 2 s. * **Availability:** 99.9% per quarter on Didit's side; downstream source availability varies by country and dataset. ## Continue reading * [Dominican Republic Database Validation overview](/api-reference/database-validation/dominican-republic) * [Database Validation overview](/core-technology/database-validation/overview) * [Outcome Codes](/core-technology/database-validation/database-validation-outcome-codes) # Ecuador - Cédula verification Source: https://docs.didit.me/api-reference/database-validation/ecuador/cedula POST /v3/database-validation/ Verifies Ecuadorian Cédula against the Registro Civil records. Authoritative real-time identity lookup for Ecuador. Real-time lookup, pay-per-call.
Verifies Ecuadorian Cédula against the Registro Civil records. Didit exposes this service through `POST /v3/database-validation/` so you can verify the submitted data against the authoritative source and receive normalized match results. ## Coverage * **Coverage:** — * **Country:** Ecuador * **Service ID:** `ecu_cedula` * **Data domain:** Identity * **Category:** NationalIDRegistry ## Inputs | Field | Required | Example | | ----------------- | -------: | ------------ | | `personal_number` | Yes | `1111111111` | | `first_name` | No | `John` | | `last_name` | No | `Doe` | | `vendor_data` | No | `user-1234` | * **Required inputs:** `personal_number` * **Optional inputs:** `first_name`, `last_name`, `vendor_data` * **Consent:** Not required * **Workflow availability:** Available in workflow * **Coverage:** — * **Price:** \$0.20 per successful query ## Body parameters ISO 3166-1 alpha-3 country code for this database service. Example: `ECU` Array containing this service ID. Pinning the service keeps the request scoped to this exact database. Example: `ecu_cedula` Country-specific personal identity number. Example: `1111111111` Given name to validate. Example: `John` Family name to validate. Example: `Doe` Your stable user reference for this person, such as your internal user ID. Didit uses it to link standalone checks to the same end user and reduce duplicate-detection noise. Example: `user-1234` ## Input rules & validation notes * Ecuadorian Cédula (exactly 10 digits) * `personal_number` must contain digits only; remove spaces, hyphens, and punctuation before sending the request. * `personal_number` must be exactly 10 characters long. ## How to call it ```bash cURL theme={null} curl -X POST "https://verification.didit.me/v3/database-validation/" \ -H "x-api-key: YOUR_API_KEY" \ -F "issuing_state=ECU" \ -F "services=ecu_cedula" \ -F "vendor_data=user-1234" \ -F "personal_number=1111111111" ``` Every successful call returns HTTP `200`. The **`outcome_code`** field tells you what actually happened — distinguishing, for example, a real biometric mismatch (`BIOMETRIC_NO_MATCH`) from a selfie that could not be read (`BIOMETRIC_IMAGE_UNUSABLE`). The `status` shown is the default feature status; your configured [Partial Match / No Match actions](/core-technology/database-validation/database-validation-warnings) can override it. **`MATCH`** — The registry confirmed the identity and every checked field matched. ```json 200 OK — MATCH theme={null} { "request_id": "req_01H…", "status": "Approved", "issuing_state": "ECU", "match_type": "full_match", "validations": [ { "outcome_code": "MATCH", "service_id": "ecu_cedula", "service_name": "Ecuador - Cédula verification", "source_data": { "first_name": "John", "identification_number": "SAMPLE-ID-12345", "last_name": "Doe" }, "validation": { "identification_number": "full_match" } } ] } ``` **`NO_MATCH`** — The registry returned no match for the submitted data. ```json 200 OK — NO_MATCH theme={null} { "request_id": "req_01H…", "status": "Declined", "issuing_state": "ECU", "match_type": "no_match", "validations": [ { "outcome_code": "NO_MATCH", "service_id": "ecu_cedula", "service_name": "Ecuador - Cédula verification", "source_data": { "identification_number": "NO_MATCH" }, "validation": { "identification_number": "no_match" } } ] } ``` ## Returned data The exact fields surfaced in `source_data` depend on what the registry returns. The generated example for `ecu_cedula` currently documents this normalized shape: * `first_name` * `identification_number` * `last_name` ## Pricing & SLAs Ecuador - Cédula verification queries are billed only when Didit receives a conclusive result from the validation source. * **Per-call price:** \$0.20 USD. * **Billing:** per successful query. You are not charged when the registry is unreachable, when required fields are missing, or when the request is rejected before reaching the source. * **Latency:** typical p95 \< 2 s. * **Availability:** 99.9% per quarter on Didit's side; downstream source availability varies by country and dataset. ## Continue reading * [Ecuador Database Validation overview](/api-reference/database-validation/ecuador) * [Database Validation overview](/core-technology/database-validation/overview) * [Outcome Codes](/core-technology/database-validation/database-validation-outcome-codes) # El Salvador - DUI verification Source: https://docs.didit.me/api-reference/database-validation/el-salvador/dui POST /v3/database-validation/ Verifies Salvadoran DUI data against RNPN government records. Authoritative real-time identity lookup for El Salvador. Real-time lookup, pay-per-call.
Verifies Salvadoran DUI data against RNPN government records. Didit exposes this service through `POST /v3/database-validation/` so you can verify the submitted data against the authoritative source and receive normalized match results. ## Coverage * **Coverage:** 90-95% * **Country:** El Salvador * **Service ID:** `slv_dui` * **Data domain:** Identity * **Category:** NationalIDRegistry ## Inputs | Field | Required | Example | | ----------------- | -------: | ------------ | | `document_number` | Yes | `111111111` | | `date_of_birth` | Yes | `1990-01-01` | | `first_name` | No | `John` | | `last_name` | No | `Doe` | | `vendor_data` | No | `user-1234` | * **Required inputs:** `document_number`, `date_of_birth` * **Optional inputs:** `first_name`, `last_name`, `vendor_data` * **Consent:** Not required * **Workflow availability:** Available in workflow * **Coverage:** 90-95% * **Price:** \$0.20 per successful query ## Body parameters ISO 3166-1 alpha-3 country code for this database service. Example: `SLV` Array containing this service ID. Pinning the service keeps the request scoped to this exact database. Example: `slv_dui` Document number extracted from or provided by the user. Example: `111111111` Date of birth in `YYYY-MM-DD` format. Example: `1990-01-01` Given name to validate. Example: `John` Family name to validate. Example: `Doe` Your stable user reference for this person, such as your internal user ID. Didit uses it to link standalone checks to the same end user and reduce duplicate-detection noise. Example: `user-1234` ## Input rules & validation notes * Salvadoran DUI (exactly 9 digits) * `document_number` must contain digits only; remove spaces, hyphens, and punctuation before sending the request. * `document_number` must be exactly 9 characters long. ## How to call it ```bash cURL theme={null} curl -X POST "https://verification.didit.me/v3/database-validation/" \ -H "x-api-key: YOUR_API_KEY" \ -F "issuing_state=SLV" \ -F "services=slv_dui" \ -F "vendor_data=user-1234" \ -F "document_number=111111111" \ -F "date_of_birth=1990-01-01" ``` Every successful call returns HTTP `200`. The **`outcome_code`** field tells you what actually happened — distinguishing, for example, a real biometric mismatch (`BIOMETRIC_NO_MATCH`) from a selfie that could not be read (`BIOMETRIC_IMAGE_UNUSABLE`). The `status` shown is the default feature status; your configured [Partial Match / No Match actions](/core-technology/database-validation/database-validation-warnings) can override it. **`MATCH`** — The registry confirmed the identity and every checked field matched. ```json 200 OK — MATCH theme={null} { "request_id": "req_01H…", "status": "Approved", "issuing_state": "SLV", "match_type": "full_match", "validations": [ { "outcome_code": "MATCH", "service_id": "slv_dui", "service_name": "El Salvador - DUI verification", "source_data": { "full_name": "John Doe", "identification_number": "SAMPLE-ID-12345" }, "validation": { "date_of_birth": "full_match", "identification_number": "full_match" } } ] } ``` **`PARTIAL_MATCH`** — The identification number was found but one or more personal fields (usually name or date of birth) did not fully match. ```json 200 OK — PARTIAL_MATCH theme={null} { "request_id": "req_01H…", "status": "In Review", "issuing_state": "SLV", "match_type": "partial_match", "validations": [ { "outcome_code": "PARTIAL_MATCH", "service_id": "slv_dui", "service_name": "El Salvador - DUI verification", "source_data": { "full_name": "John Doe", "identification_number": "SAMPLE-ID-12345" }, "validation": { "date_of_birth": "no_match", "identification_number": "full_match" } } ] } ``` **`NO_MATCH`** — The registry returned no match for the submitted data. ```json 200 OK — NO_MATCH theme={null} { "request_id": "req_01H…", "status": "Declined", "issuing_state": "SLV", "match_type": "no_match", "validations": [ { "outcome_code": "NO_MATCH", "service_id": "slv_dui", "service_name": "El Salvador - DUI verification", "source_data": { "date_of_birth": "NO_MATCH", "identification_number": "NO_MATCH" }, "validation": { "date_of_birth": "no_match", "identification_number": "no_match" } } ] } ``` ## Returned data The exact fields surfaced in `source_data` depend on what the registry returns. The generated example for `slv_dui` currently documents this normalized shape: * `full_name` * `identification_number` ## Pricing & SLAs El Salvador - DUI verification queries are billed only when Didit receives a conclusive result from the validation source. * **Per-call price:** \$0.20 USD. * **Billing:** per successful query. You are not charged when the registry is unreachable, when required fields are missing, or when the request is rejected before reaching the source. * **Latency:** typical p95 \< 2 s. * **Availability:** 99.9% per quarter on Didit's side; downstream source availability varies by country and dataset. ## Continue reading * [El Salvador Database Validation overview](/api-reference/database-validation/el-salvador) * [Database Validation overview](/core-technology/database-validation/overview) * [Outcome Codes](/core-technology/database-validation/database-validation-outcome-codes) # Finland Consumer 2 Source: https://docs.didit.me/api-reference/database-validation/finland/consumer-2 POST /v3/database-validation/ Verifies Finland Consumer 2. Authoritative real-time identity lookup for Finland. Real-time lookup, pay-per-call.
Verifies Finland Consumer 2. Didit exposes this service through `POST /v3/database-validation/` so you can verify the submitted data against the authoritative source and receive normalized match results. ## Coverage * **Coverage:** — * **Country:** Finland * **Service ID:** `fin_consumer_2` * **Data domain:** Address * **Category:** Residential ## Inputs | Field | Required | Example | | --------------------- | -------: | ---------------------- | | `first_name` | Yes | `John` | | `last_name` | Yes | `Doe` | | `date_of_birth` | Yes | `1990-01-01` | | `address.street_1` | No | `123 Sample Street` | | `address.street_2` | No | `Unit 4` | | `address.city` | No | `Sample City` | | `address.region` | No | `Sample State` | | `address.postal_code` | No | `10001` | | `phone` | No | `+15550101000` | | `email` | No | `john.doe@example.com` | | `vendor_data` | No | `user-1234` | * **Required inputs:** `first_name`, `last_name`, `date_of_birth` * **Optional inputs:** `address.street_1`, `address.street_2`, `address.city`, `address.region`, `address.postal_code`, `phone`, `email`, `vendor_data` * **Consent:** Not required * **Workflow availability:** Available in workflow * **Coverage:** — * **Price:** \$0.97 per successful query ## Body parameters ISO 3166-1 alpha-3 country code for this database service. Example: `FIN` Array containing this service ID. Pinning the service keeps the request scoped to this exact database. Example: `fin_consumer_2` Given name to validate. Example: `John` Family name to validate. Example: `Doe` Date of birth in `YYYY-MM-DD` format. Example: `1990-01-01` Structured residential address object. Use `street_1`, `street_2`, `city`, `region`, `postal_code`, and `country`. A complete legacy address string is still accepted but not recommended. Example: `{"street_1":"123 Sample Street","street_2":"Unit 4","city":"Sample City","region":"Sample State","postal_code":"10001","country":"US"}` Phone number in international format. Example: `+15550101000` Email address. Example: `john.doe@example.com` Your stable user reference for this person, such as your internal user ID. Didit uses it to link standalone checks to the same end user and reduce duplicate-detection noise. Example: `user-1234` ## Input rules & validation notes * `address` is optional for this service. You can send one complete `address` string and Didit will split it into structured address elements when possible, or you can send the structured fields explicitly. * For address services, send structured address fields instead of a single `address` string when possible. * `address.street_1` is the street address, including street number and street type. * `address.street_2` is apartment, unit, building, floor, or extra address line. Send it only when you have it. * `address.city` is city, suburb, district, locality, or neighborhood. * `address.region` is state, province, region, or town. * `address.postal_code` is postcode or postal code. * Address-based database services require at least street address and postal code; requests rejected before source lookup are not charged. ## How to call it ```bash cURL theme={null} curl -X POST "https://verification.didit.me/v3/database-validation/" \ -H "x-api-key: YOUR_API_KEY" \ -F "issuing_state=FIN" \ -F "services=fin_consumer_2" \ -F "vendor_data=user-1234" \ -F "first_name=John" \ -F "last_name=Doe" \ -F "date_of_birth=1990-01-01" ``` Every successful call returns HTTP `200`. The **`outcome_code`** field tells you what actually happened — distinguishing, for example, a real biometric mismatch (`BIOMETRIC_NO_MATCH`) from a selfie that could not be read (`BIOMETRIC_IMAGE_UNUSABLE`). The `status` shown is the default feature status; your configured [Partial Match / No Match actions](/core-technology/database-validation/database-validation-warnings) can override it. **`MATCH`** — The registry confirmed the identity and every checked field matched. ```json 200 OK — MATCH theme={null} { "request_id": "req_01H…", "status": "Approved", "issuing_state": "FIN", "match_type": "full_match", "validations": [ { "outcome_code": "MATCH", "service_id": "fin_consumer_2", "service_name": "Finland Consumer 2", "source_data": { "address": "123 Sample Street", "date_of_birth": "1990-01-01", "first_name": "John", "last_name": "Doe" }, "validation": { "date_of_birth": "full_match", "full_name": "full_match" } } ] } ``` **`PARTIAL_MATCH`** — The identification number was found but one or more personal fields (usually name or date of birth) did not fully match. ```json 200 OK — PARTIAL_MATCH theme={null} { "request_id": "req_01H…", "status": "In Review", "issuing_state": "FIN", "match_type": "partial_match", "validations": [ { "outcome_code": "PARTIAL_MATCH", "service_id": "fin_consumer_2", "service_name": "Finland Consumer 2", "source_data": { "address": "123 Sample Street", "date_of_birth": "1990-01-01", "first_name": "John", "last_name": "Doe" }, "validation": { "date_of_birth": "full_match", "full_name": "no_match" } } ] } ``` **`NO_MATCH`** — The registry returned no match for the submitted data. ```json 200 OK — NO_MATCH theme={null} { "request_id": "req_01H…", "status": "Declined", "issuing_state": "FIN", "match_type": "no_match", "validations": [ { "outcome_code": "NO_MATCH", "service_id": "fin_consumer_2", "service_name": "Finland Consumer 2", "source_data": { "date_of_birth": "NO_MATCH", "full_name": "NO_MATCH" }, "validation": { "date_of_birth": "no_match", "full_name": "no_match" } } ] } ``` ## Returned data The exact fields surfaced in `source_data` depend on what the registry returns. The generated example for `fin_consumer_2` currently documents this normalized shape: * `address` * `date_of_birth` * `first_name` * `last_name` ## Pricing & SLAs Finland Consumer 2 queries are billed only when Didit receives a conclusive result from the validation source. * **Per-call price:** \$0.97 USD. * **Billing:** per successful query. You are not charged when the registry is unreachable, when required fields are missing, or when the request is rejected before reaching the source. * **Latency:** typical p95 \< 2 s. * **Availability:** 99.9% per quarter on Didit's side; downstream source availability varies by country and dataset. ## Continue reading * [Finland Database Validation overview](/api-reference/database-validation/finland) * [Database Validation overview](/core-technology/database-validation/overview) * [Outcome Codes](/core-technology/database-validation/database-validation-outcome-codes) # Finland National ID Source: https://docs.didit.me/api-reference/database-validation/finland/national-id POST /v3/database-validation/ Verifies input data against the official issuing agency of the Finnish Identity Card. Authoritative real-time identity lookup for Finland. Real-time lookup, pay-per-call.
Verifies input data against the official issuing agency of the Finnish Identity Card. Didit exposes this service through `POST /v3/database-validation/` so you can verify the submitted data against the authoritative source and receive normalized match results. ## Coverage * **Coverage:** \~ 100% * **Country:** Finland * **Service ID:** `fin_national_id` * **Data domain:** Identity * **Category:** NationalIDRegistry ## Inputs | Field | Required | Example | | --------------------- | -------: | ------------------- | | `first_name` | Yes | `John` | | `last_name` | Yes | `Doe` | | `date_of_birth` | Yes | `1990-01-01` | | `national_id` | Yes | `SAMPLE-NID-12345` | | `address.street_1` | No | `123 Sample Street` | | `address.street_2` | No | `Unit 4` | | `address.city` | No | `Sample City` | | `address.region` | No | `Sample State` | | `address.postal_code` | No | `10001` | | `vendor_data` | No | `user-1234` | * **Required inputs:** `first_name`, `last_name`, `date_of_birth`, `national_id` * **Optional inputs:** `address.street_1`, `address.street_2`, `address.city`, `address.region`, `address.postal_code`, `vendor_data` * **Consent:** Required * **Workflow availability:** Available in workflow * **Coverage:** \~ 100% * **Price:** \$2.10 per successful query Not every document this service accepts carries the identifier it queries by. When the identifier is not extracted from the document the check is recorded as **not applicable** - no database is queried and you are not charged - which for some countries is a large share of real users. To cover them, also collect the identifier from a Questionnaire answer, a Document AI extraction field, or a value you send when you create the session, and map it on the Database Validation step. ## Body parameters ISO 3166-1 alpha-3 country code for this database service. Example: `FIN` Array containing this service ID. Pinning the service keeps the request scoped to this exact database. Example: `fin_national_id` Explicit end-user consent for this service. Example: `true` Given name to validate. Example: `John` Family name to validate. Example: `Doe` Date of birth in `YYYY-MM-DD` format. Example: `1990-01-01` National identity number for this service. Example: `SAMPLE-NID-12345` Structured residential address object. Use `street_1`, `street_2`, `city`, `region`, `postal_code`, and `country`. A complete legacy address string is still accepted but not recommended. Example: `{"street_1":"123 Sample Street","street_2":"Unit 4","city":"Sample City","region":"Sample State","postal_code":"10001","country":"US"}` Your stable user reference for this person, such as your internal user ID. Didit uses it to link standalone checks to the same end user and reduce duplicate-detection noise. Example: `user-1234` ## Input rules & validation notes * `address` is optional for this service. You can send one complete `address` string and Didit will split it into structured address elements when possible, or you can send the structured fields explicitly. * `national_id` must match `(?:\d{6}[-+A]\d{3}[0-9A-Z]|\d{6}\d{3}[0-9A-Z])`. * For address services, send structured address fields instead of a single `address` string when possible. * `address.street_1` is the street address, including street number and street type. * `address.street_2` is apartment, unit, building, floor, or extra address line. Send it only when you have it. * `address.city` is city, suburb, district, locality, or neighborhood. * `address.region` is state, province, region, or town. * `address.postal_code` is postcode or postal code. * Address-based database services require at least street address and postal code; requests rejected before source lookup are not charged. ## How to call it ```bash cURL theme={null} curl -X POST "https://verification.didit.me/v3/database-validation/" \ -H "x-api-key: YOUR_API_KEY" \ -F "issuing_state=FIN" \ -F "services=fin_national_id" \ -F "vendor_data=user-1234" \ -F "consent=true" \ -F "first_name=John" \ -F "last_name=Doe" \ -F "date_of_birth=1990-01-01" \ -F "national_id=SAMPLE-NID-12345" ``` Every successful call returns HTTP `200`. The **`outcome_code`** field tells you what actually happened — distinguishing, for example, a real biometric mismatch (`BIOMETRIC_NO_MATCH`) from a selfie that could not be read (`BIOMETRIC_IMAGE_UNUSABLE`). The `status` shown is the default feature status; your configured [Partial Match / No Match actions](/core-technology/database-validation/database-validation-warnings) can override it. **`MATCH`** — The registry confirmed the identity and every checked field matched. ```json 200 OK — MATCH theme={null} { "request_id": "req_01H…", "status": "Approved", "issuing_state": "FIN", "match_type": "full_match", "validations": [ { "outcome_code": "MATCH", "service_id": "fin_national_id", "service_name": "Finland National ID", "source_data": { "address": "123 Sample Street", "date_of_birth": "1990-01-01", "first_name": "John", "identification_number": "SAMPLE-ID-12345", "last_name": "Doe" }, "validation": { "date_of_birth": "full_match", "full_name": "full_match", "identification_number": "full_match" } } ] } ``` **`PARTIAL_MATCH`** — The identification number was found but one or more personal fields (usually name or date of birth) did not fully match. ```json 200 OK — PARTIAL_MATCH theme={null} { "request_id": "req_01H…", "status": "In Review", "issuing_state": "FIN", "match_type": "partial_match", "validations": [ { "outcome_code": "PARTIAL_MATCH", "service_id": "fin_national_id", "service_name": "Finland National ID", "source_data": { "address": "123 Sample Street", "date_of_birth": "1990-01-01", "first_name": "John", "identification_number": "SAMPLE-ID-12345", "last_name": "Doe" }, "validation": { "date_of_birth": "full_match", "full_name": "no_match", "identification_number": "full_match" } } ] } ``` **`NO_MATCH`** — The registry returned no match for the submitted data. ```json 200 OK — NO_MATCH theme={null} { "request_id": "req_01H…", "status": "Declined", "issuing_state": "FIN", "match_type": "no_match", "validations": [ { "outcome_code": "NO_MATCH", "service_id": "fin_national_id", "service_name": "Finland National ID", "source_data": { "date_of_birth": "NO_MATCH", "full_name": "NO_MATCH", "identification_number": "NO_MATCH" }, "validation": { "date_of_birth": "no_match", "full_name": "no_match", "identification_number": "no_match" } } ] } ``` ## Returned data The exact fields surfaced in `source_data` depend on what the registry returns. The generated example for `fin_national_id` currently documents this normalized shape: * `address` * `date_of_birth` * `first_name` * `identification_number` * `last_name` ## Pricing & SLAs Finland National ID queries are billed only when Didit receives a conclusive result from the validation source. * **Per-call price:** \$2.10 USD. * **Billing:** per successful query. You are not charged when the registry is unreachable, when required fields are missing, or when the request is rejected before reaching the source. * **Latency:** typical p95 \< 2 s. * **Availability:** 99.9% per quarter on Didit's side; downstream source availability varies by country and dataset. ## Continue reading * [Finland Database Validation overview](/api-reference/database-validation/finland) * [Database Validation overview](/core-technology/database-validation/overview) * [Outcome Codes](/core-technology/database-validation/database-validation-outcome-codes) # France Phone Source: https://docs.didit.me/api-reference/database-validation/france/phone POST /v3/database-validation/ Verifies input data to mobile network operators phone data. Authoritative real-time identity lookup for France. Real-time lookup, pay-per-call.
Verifies input data to mobile network operators phone data. Didit exposes this service through `POST /v3/database-validation/` so you can verify the submitted data against the authoritative source and receive normalized match results. ## Coverage * **Coverage:** \~ 90% * **Country:** France * **Service ID:** `fra_phone` * **Data domain:** Telecom * **Category:** Telecom ## Inputs | Field | Required | Example | | --------------------- | -------: | ------------------- | | `first_name` | Yes | `John` | | `last_name` | Yes | `Doe` | | `phone` | Yes | `+15550101000` | | `date_of_birth` | No | `1990-01-01` | | `address.street_1` | No | `123 Sample Street` | | `address.street_2` | No | `Unit 4` | | `address.city` | No | `Sample City` | | `address.region` | No | `Sample State` | | `address.postal_code` | No | `10001` | | `vendor_data` | No | `user-1234` | * **Required inputs:** `first_name`, `last_name`, `phone` * **Optional inputs:** `date_of_birth`, `address.street_1`, `address.street_2`, `address.city`, `address.region`, `address.postal_code`, `vendor_data` * **Consent:** Not required * **Workflow availability:** Available in workflow * **Coverage:** \~ 90% * **Price:** \$0.67 per successful query ## Body parameters ISO 3166-1 alpha-3 country code for this database service. Example: `FRA` Array containing this service ID. Pinning the service keeps the request scoped to this exact database. Example: `fra_phone` Given name to validate. Example: `John` Family name to validate. Example: `Doe` Phone number in international format. Example: `+15550101000` Date of birth in `YYYY-MM-DD` format. Example: `1990-01-01` Structured residential address object. Use `street_1`, `street_2`, `city`, `region`, `postal_code`, and `country`. A complete legacy address string is still accepted but not recommended. Example: `{"street_1":"123 Sample Street","street_2":"Unit 4","city":"Sample City","region":"Sample State","postal_code":"10001","country":"US"}` Your stable user reference for this person, such as your internal user ID. Didit uses it to link standalone checks to the same end user and reduce duplicate-detection noise. Example: `user-1234` ## Input rules & validation notes * `address` is optional for this service. You can send one complete `address` string and Didit will split it into structured address elements when possible, or you can send the structured fields explicitly. * For address services, send structured address fields instead of a single `address` string when possible. * `address.street_1` is the street address, including street number and street type. * `address.street_2` is apartment, unit, building, floor, or extra address line. Send it only when you have it. * `address.city` is city, suburb, district, locality, or neighborhood. * `address.region` is state, province, region, or town. * `address.postal_code` is postcode or postal code. * Address-based database services require at least street address and postal code; requests rejected before source lookup are not charged. ## How to call it ```bash cURL theme={null} curl -X POST "https://verification.didit.me/v3/database-validation/" \ -H "x-api-key: YOUR_API_KEY" \ -F "issuing_state=FRA" \ -F "services=fra_phone" \ -F "vendor_data=user-1234" \ -F "first_name=John" \ -F "last_name=Doe" \ -F "phone=+15550101000" ``` Every successful call returns HTTP `200`. The **`outcome_code`** field tells you what actually happened — distinguishing, for example, a real biometric mismatch (`BIOMETRIC_NO_MATCH`) from a selfie that could not be read (`BIOMETRIC_IMAGE_UNUSABLE`). The `status` shown is the default feature status; your configured [Partial Match / No Match actions](/core-technology/database-validation/database-validation-warnings) can override it. **`MATCH`** — The registry confirmed the identity and every checked field matched. ```json 200 OK — MATCH theme={null} { "request_id": "req_01H…", "status": "Approved", "issuing_state": "FRA", "match_type": "full_match", "validations": [ { "outcome_code": "MATCH", "service_id": "fra_phone", "service_name": "France Phone", "source_data": { "address": "123 Sample Street", "date_of_birth": "1990-01-01", "first_name": "John", "last_name": "Doe" }, "validation": { "full_name": "full_match" } } ] } ``` **`NO_MATCH`** — The registry returned no match for the submitted data. ```json 200 OK — NO_MATCH theme={null} { "request_id": "req_01H…", "status": "Declined", "issuing_state": "FRA", "match_type": "no_match", "validations": [ { "outcome_code": "NO_MATCH", "service_id": "fra_phone", "service_name": "France Phone", "source_data": { "full_name": "NO_MATCH" }, "validation": { "full_name": "no_match" } } ] } ``` ## Returned data The exact fields surfaced in `source_data` depend on what the registry returns. The generated example for `fra_phone` currently documents this normalized shape: * `address` * `date_of_birth` * `first_name` * `last_name` ## Pricing & SLAs France Phone queries are billed only when Didit receives a conclusive result from the validation source. * **Per-call price:** \$0.67 USD. * **Billing:** per successful query. You are not charged when the registry is unreachable, when required fields are missing, or when the request is rejected before reaching the source. * **Latency:** typical p95 \< 2 s. * **Availability:** 99.9% per quarter on Didit's side; downstream source availability varies by country and dataset. ## Continue reading * [France Database Validation overview](/api-reference/database-validation/france) * [Database Validation overview](/core-technology/database-validation/overview) * [Outcome Codes](/core-technology/database-validation/database-validation-outcome-codes) # France Residential Source: https://docs.didit.me/api-reference/database-validation/france/residential POST /v3/database-validation/ Verifies data against government agency sourced census data. Authoritative real-time identity lookup for France. Real-time lookup, pay-per-call.
Verifies data against government agency sourced census data. Didit exposes this service through `POST /v3/database-validation/` so you can verify the submitted data against the authoritative source and receive normalized match results. ## Coverage * **Coverage:** \~ 85% * **Country:** France * **Service ID:** `fra_residential` * **Data domain:** Address * **Category:** Residential ## Inputs | Field | Required | Example | | --------------------- | -------: | ------------------- | | `first_name` | Yes | `John` | | `last_name` | Yes | `Doe` | | `date_of_birth` | Yes | `1990-01-01` | | `address.street_1` | Yes | `123 Sample Street` | | `address.postal_code` | Yes | `10001` | | `address.street_2` | No | `Unit 4` | | `address.city` | No | `Sample City` | | `address.region` | No | `Sample State` | | `vendor_data` | No | `user-1234` | * **Required inputs:** `first_name`, `last_name`, `date_of_birth`, `address.street_1`, `address.postal_code` * **Optional inputs:** `address.street_2`, `address.city`, `address.region`, `vendor_data` * **Consent:** Not required * **Workflow availability:** Available in workflow * **Coverage:** \~ 85% * **Price:** \$0.89 per successful query ## Body parameters ISO 3166-1 alpha-3 country code for this database service. Example: `FRA` Array containing this service ID. Pinning the service keeps the request scoped to this exact database. Example: `fra_residential` Given name to validate. Example: `John` Family name to validate. Example: `Doe` Date of birth in `YYYY-MM-DD` format. Example: `1990-01-01` Structured residential address object. Use `street_1`, `street_2`, `city`, `region`, `postal_code`, and `country`. A complete legacy address string is still accepted but not recommended. Example: `{"street_1":"123 Sample Street","street_2":"Unit 4","city":"Sample City","region":"Sample State","postal_code":"10001","country":"US"}` Your stable user reference for this person, such as your internal user ID. Didit uses it to link standalone checks to the same end user and reduce duplicate-detection noise. Example: `user-1234` ## Input rules & validation notes * For address services, send structured address fields instead of a single `address` string when possible. * `address.street_1` is the street address, including street number and street type. * `address.street_2` is apartment, unit, building, floor, or extra address line. Send it only when you have it. * `address.city` is city, suburb, district, locality, or neighborhood. * `address.region` is state, province, region, or town. * `address.postal_code` is postcode or postal code. * Address-based database services require at least street address and postal code; requests rejected before source lookup are not charged. ## How to call it ```bash cURL theme={null} curl -X POST "https://verification.didit.me/v3/database-validation/" \ -H "x-api-key: YOUR_API_KEY" \ -F "issuing_state=FRA" \ -F "services=fra_residential" \ -F "vendor_data=user-1234" \ -F "first_name=John" \ -F "last_name=Doe" \ -F "date_of_birth=1990-01-01" \ -F 'address={"street_1":"123 Sample Street","street_2":"Unit 4","city":"Sample City","region":"Sample State","postal_code":"10001","country":"US"}' ``` Every successful call returns HTTP `200`. The **`outcome_code`** field tells you what actually happened — distinguishing, for example, a real biometric mismatch (`BIOMETRIC_NO_MATCH`) from a selfie that could not be read (`BIOMETRIC_IMAGE_UNUSABLE`). The `status` shown is the default feature status; your configured [Partial Match / No Match actions](/core-technology/database-validation/database-validation-warnings) can override it. **`MATCH`** — The registry confirmed the identity and every checked field matched. ```json 200 OK — MATCH theme={null} { "request_id": "req_01H…", "status": "Approved", "issuing_state": "FRA", "match_type": "full_match", "validations": [ { "outcome_code": "MATCH", "service_id": "fra_residential", "service_name": "France Residential", "source_data": { "address": "123 Sample Street", "address_match_score": "1.000", "city": "Sample City", "date_of_birth": "1990-01-01", "first_name": "John", "full_name": "John Doe", "last_name": "Doe", "name_match_score": "1.000", "postal_code": "10001", "street": "sample_value" }, "validation": { "address": "full_match", "date_of_birth": "full_match", "full_name": "full_match" } } ] } ``` **`PARTIAL_MATCH`** — The identification number was found but one or more personal fields (usually name or date of birth) did not fully match. ```json 200 OK — PARTIAL_MATCH theme={null} { "request_id": "req_01H…", "status": "In Review", "issuing_state": "FRA", "match_type": "partial_match", "validations": [ { "outcome_code": "PARTIAL_MATCH", "service_id": "fra_residential", "service_name": "France Residential", "source_data": { "address": "123 Sample Street", "address_match_score": "1.000", "city": "Sample City", "date_of_birth": "1990-01-01", "first_name": "John", "full_name": "John Doe", "last_name": "Doe", "name_match_score": "1.000", "postal_code": "10001", "street": "sample_value" }, "validation": { "address": "full_match", "date_of_birth": "full_match", "full_name": "no_match" } } ] } ``` **`NO_MATCH`** — The registry returned no match for the submitted data. ```json 200 OK — NO_MATCH theme={null} { "request_id": "req_01H…", "status": "Declined", "issuing_state": "FRA", "match_type": "no_match", "validations": [ { "outcome_code": "NO_MATCH", "service_id": "fra_residential", "service_name": "France Residential", "source_data": { "address": "NO_MATCH", "date_of_birth": "NO_MATCH", "full_name": "NO_MATCH" }, "validation": { "address": "no_match", "date_of_birth": "no_match", "full_name": "no_match" } } ] } ``` ## Returned data The exact fields surfaced in `source_data` depend on what the registry returns. The generated example for `fra_residential` currently documents this normalized shape: * `address` * `address_match_score` * `city` * `date_of_birth` * `first_name` * `full_name` * `last_name` * `name_match_score` * `postal_code` * `street` ## Pricing & SLAs France Residential queries are billed only when Didit receives a conclusive result from the validation source. * **Per-call price:** \$0.89 USD. * **Billing:** per successful query. You are not charged when the registry is unreachable, when required fields are missing, or when the request is rejected before reaching the source. * **Latency:** typical p95 \< 2 s. * **Availability:** 99.9% per quarter on Didit's side; downstream source availability varies by country and dataset. ## Continue reading * [France Database Validation overview](/api-reference/database-validation/france) * [Database Validation overview](/core-technology/database-validation/overview) * [Outcome Codes](/core-technology/database-validation/database-validation-outcome-codes) # France Utility Source: https://docs.didit.me/api-reference/database-validation/france/utility POST /v3/database-validation/ Aggregated service of public records, background records, and public professional profiles. Authoritative real-time identity lookup for France. Real-time lookup, pay-per-call.
Aggregated service of public records, background records, and public professional profiles. Didit exposes this service through `POST /v3/database-validation/` so you can verify the submitted data against the authoritative source and receive normalized match results. ## Coverage * **Coverage:** > 75% * **Country:** France * **Service ID:** `fra_utility` * **Data domain:** Address * **Category:** Utility ## Inputs | Field | Required | Example | | --------------------- | -------: | ------------------- | | `first_name` | Yes | `John` | | `last_name` | Yes | `Doe` | | `date_of_birth` | Yes | `1990-01-01` | | `address.street_1` | Yes | `123 Sample Street` | | `address.postal_code` | Yes | `10001` | | `address.street_2` | No | `Unit 4` | | `address.city` | No | `Sample City` | | `address.region` | No | `Sample State` | | `vendor_data` | No | `user-1234` | * **Required inputs:** `first_name`, `last_name`, `date_of_birth`, `address.street_1`, `address.postal_code` * **Optional inputs:** `address.street_2`, `address.city`, `address.region`, `vendor_data` * **Consent:** Not required * **Workflow availability:** Available in workflow * **Coverage:** > 75% * **Price:** \$0.65 per successful query ## Body parameters ISO 3166-1 alpha-3 country code for this database service. Example: `FRA` Array containing this service ID. Pinning the service keeps the request scoped to this exact database. Example: `fra_utility` Given name to validate. Example: `John` Family name to validate. Example: `Doe` Date of birth in `YYYY-MM-DD` format. Example: `1990-01-01` Structured residential address object. Use `street_1`, `street_2`, `city`, `region`, `postal_code`, and `country`. A complete legacy address string is still accepted but not recommended. Example: `{"street_1":"123 Sample Street","street_2":"Unit 4","city":"Sample City","region":"Sample State","postal_code":"10001","country":"US"}` Your stable user reference for this person, such as your internal user ID. Didit uses it to link standalone checks to the same end user and reduce duplicate-detection noise. Example: `user-1234` ## Input rules & validation notes * For address services, send structured address fields instead of a single `address` string when possible. * `address.street_1` is the street address, including street number and street type. * `address.street_2` is apartment, unit, building, floor, or extra address line. Send it only when you have it. * `address.city` is city, suburb, district, locality, or neighborhood. * `address.region` is state, province, region, or town. * `address.postal_code` is postcode or postal code. * Address-based database services require at least street address and postal code; requests rejected before source lookup are not charged. ## How to call it ```bash cURL theme={null} curl -X POST "https://verification.didit.me/v3/database-validation/" \ -H "x-api-key: YOUR_API_KEY" \ -F "issuing_state=FRA" \ -F "services=fra_utility" \ -F "vendor_data=user-1234" \ -F "first_name=John" \ -F "last_name=Doe" \ -F "date_of_birth=1990-01-01" \ -F 'address={"street_1":"123 Sample Street","street_2":"Unit 4","city":"Sample City","region":"Sample State","postal_code":"10001","country":"US"}' ``` Every successful call returns HTTP `200`. The **`outcome_code`** field tells you what actually happened — distinguishing, for example, a real biometric mismatch (`BIOMETRIC_NO_MATCH`) from a selfie that could not be read (`BIOMETRIC_IMAGE_UNUSABLE`). The `status` shown is the default feature status; your configured [Partial Match / No Match actions](/core-technology/database-validation/database-validation-warnings) can override it. **`MATCH`** — The registry confirmed the identity and every checked field matched. ```json 200 OK — MATCH theme={null} { "request_id": "req_01H…", "status": "Approved", "issuing_state": "FRA", "match_type": "full_match", "validations": [ { "outcome_code": "MATCH", "service_id": "fra_utility", "service_name": "France Utility", "source_data": { "address_match_score": "1.000", "date_of_birth": "1990-01-01", "first_name": "John", "full_name": "John Doe", "last_name": "Doe", "name_match_score": "1.000", "verifications": { "address": true, "date_of_birth": true, "full_name": true } }, "validation": { "address": "full_match", "date_of_birth": "full_match", "full_name": "full_match" } } ] } ``` **`PARTIAL_MATCH`** — The identification number was found but one or more personal fields (usually name or date of birth) did not fully match. ```json 200 OK — PARTIAL_MATCH theme={null} { "request_id": "req_01H…", "status": "In Review", "issuing_state": "FRA", "match_type": "partial_match", "validations": [ { "outcome_code": "PARTIAL_MATCH", "service_id": "fra_utility", "service_name": "France Utility", "source_data": { "address_match_score": "1.000", "date_of_birth": "1990-01-01", "first_name": "John", "full_name": "John Doe", "last_name": "Doe", "name_match_score": "1.000", "verifications": { "address": true, "date_of_birth": true, "full_name": false } }, "validation": { "address": "full_match", "date_of_birth": "full_match", "full_name": "no_match" } } ] } ``` **`NO_MATCH`** — The registry returned no match for the submitted data. ```json 200 OK — NO_MATCH theme={null} { "request_id": "req_01H…", "status": "Declined", "issuing_state": "FRA", "match_type": "no_match", "validations": [ { "outcome_code": "NO_MATCH", "service_id": "fra_utility", "service_name": "France Utility", "source_data": { "address": "NO_MATCH", "date_of_birth": "NO_MATCH", "full_name": "NO_MATCH" }, "validation": { "address": "no_match", "date_of_birth": "no_match", "full_name": "no_match" } } ] } ``` ## Returned data The exact fields surfaced in `source_data` depend on what the registry returns. The generated example for `fra_utility` currently documents this normalized shape: * `address_match_score` * `date_of_birth` * `first_name` * `full_name` * `last_name` * `name_match_score` ## Pricing & SLAs France Utility queries are billed only when Didit receives a conclusive result from the validation source. * **Per-call price:** \$0.65 USD. * **Billing:** per successful query. You are not charged when the registry is unreachable, when required fields are missing, or when the request is rejected before reaching the source. * **Latency:** typical p95 \< 2 s. * **Availability:** 99.9% per quarter on Didit's side; downstream source availability varies by country and dataset. ## Continue reading * [France Database Validation overview](/api-reference/database-validation/france) * [Database Validation overview](/core-technology/database-validation/overview) * [Outcome Codes](/core-technology/database-validation/database-validation-outcome-codes) # Germany Credit Bureau Source: https://docs.didit.me/api-reference/database-validation/germany/credit-bureau POST /v3/database-validation/ Verifies input data against Credit Header data obtained from a Credit Bureau in Germany. Authoritative real-time identity lookup for Germany. Real-time lookup, pay-per-call.
Verifies input data against Credit Header data obtained from a Credit Bureau in Germany. Didit exposes this service through `POST /v3/database-validation/` so you can verify the submitted data against the authoritative source and receive normalized match results. ## Coverage * **Coverage:** \~ 80% * **Country:** Germany * **Service ID:** `deu_credit_bureau` * **Data domain:** Financial * **Category:** CreditBureau ## Inputs | Field | Required | Example | | --------------------- | -------: | ------------------- | | `first_name` | Yes | `John` | | `last_name` | Yes | `Doe` | | `date_of_birth` | Yes | `1990-01-01` | | `address.street_1` | Yes | `123 Sample Street` | | `address.postal_code` | Yes | `10001` | | `address.street_2` | No | `Unit 4` | | `address.city` | No | `Sample City` | | `address.region` | No | `Sample State` | | `vendor_data` | No | `user-1234` | * **Required inputs:** `first_name`, `last_name`, `date_of_birth`, `address.street_1`, `address.postal_code` * **Optional inputs:** `address.street_2`, `address.city`, `address.region`, `vendor_data` * **Consent:** Required * **Workflow availability:** Available in workflow * **Coverage:** \~ 80% * **Price:** \$0.84 per successful query ## Body parameters ISO 3166-1 alpha-3 country code for this database service. Example: `DEU` Array containing this service ID. Pinning the service keeps the request scoped to this exact database. Example: `deu_credit_bureau` Explicit end-user consent for this service. Example: `true` Given name to validate. Example: `John` Family name to validate. Example: `Doe` Date of birth in `YYYY-MM-DD` format. Example: `1990-01-01` Structured residential address object. Use `street_1`, `street_2`, `city`, `region`, `postal_code`, and `country`. A complete legacy address string is still accepted but not recommended. Example: `{"street_1":"123 Sample Street","street_2":"Unit 4","city":"Sample City","region":"Sample State","postal_code":"10001","country":"US"}` Your stable user reference for this person, such as your internal user ID. Didit uses it to link standalone checks to the same end user and reduce duplicate-detection noise. Example: `user-1234` ## Input rules & validation notes * For address services, send structured address fields instead of a single `address` string when possible. * `address.street_1` is the street address, including street number and street type. * `address.street_2` is apartment, unit, building, floor, or extra address line. Send it only when you have it. * `address.city` is city, suburb, district, locality, or neighborhood. * `address.region` is state, province, region, or town. * `address.postal_code` is postcode or postal code. * Address-based database services require at least street address and postal code; requests rejected before source lookup are not charged. ## How to call it ```bash cURL theme={null} curl -X POST "https://verification.didit.me/v3/database-validation/" \ -H "x-api-key: YOUR_API_KEY" \ -F "issuing_state=DEU" \ -F "services=deu_credit_bureau" \ -F "vendor_data=user-1234" \ -F "consent=true" \ -F "first_name=John" \ -F "last_name=Doe" \ -F "date_of_birth=1990-01-01" \ -F 'address={"street_1":"123 Sample Street","street_2":"Unit 4","city":"Sample City","region":"Sample State","postal_code":"10001","country":"US"}' ``` Every successful call returns HTTP `200`. The **`outcome_code`** field tells you what actually happened — distinguishing, for example, a real biometric mismatch (`BIOMETRIC_NO_MATCH`) from a selfie that could not be read (`BIOMETRIC_IMAGE_UNUSABLE`). The `status` shown is the default feature status; your configured [Partial Match / No Match actions](/core-technology/database-validation/database-validation-warnings) can override it. **`MATCH`** — The registry confirmed the identity and every checked field matched. ```json 200 OK — MATCH theme={null} { "request_id": "req_01H…", "status": "Approved", "issuing_state": "DEU", "match_type": "full_match", "validations": [ { "outcome_code": "MATCH", "service_id": "deu_credit_bureau", "service_name": "Germany Credit Bureau", "source_data": { "address": "123 Sample Street", "address_match_score": "1.000", "city": "Sample City", "date_of_birth": "1990-01-01", "first_name": "John", "full_name": "John Doe", "last_name": "Doe", "name_match_score": "1.000", "postal_code": "10001", "street": "sample_value", "verifications": { "address": true, "date_of_birth": true, "full_name": true } }, "validation": { "address": "full_match", "date_of_birth": "full_match", "full_name": "full_match" } } ] } ``` **`PARTIAL_MATCH`** — The identification number was found but one or more personal fields (usually name or date of birth) did not fully match. ```json 200 OK — PARTIAL_MATCH theme={null} { "request_id": "req_01H…", "status": "In Review", "issuing_state": "DEU", "match_type": "partial_match", "validations": [ { "outcome_code": "PARTIAL_MATCH", "service_id": "deu_credit_bureau", "service_name": "Germany Credit Bureau", "source_data": { "address": "123 Sample Street", "address_match_score": "1.000", "city": "Sample City", "date_of_birth": "1990-01-01", "first_name": "John", "full_name": "John Doe", "last_name": "Doe", "name_match_score": "1.000", "postal_code": "10001", "street": "sample_value", "verifications": { "address": true, "date_of_birth": true, "full_name": false } }, "validation": { "address": "full_match", "date_of_birth": "full_match", "full_name": "no_match" } } ] } ``` **`NO_MATCH`** — The registry returned no match for the submitted data. ```json 200 OK — NO_MATCH theme={null} { "request_id": "req_01H…", "status": "Declined", "issuing_state": "DEU", "match_type": "no_match", "validations": [ { "outcome_code": "NO_MATCH", "service_id": "deu_credit_bureau", "service_name": "Germany Credit Bureau", "source_data": { "address": "NO_MATCH", "date_of_birth": "NO_MATCH", "full_name": "NO_MATCH" }, "validation": { "address": "no_match", "date_of_birth": "no_match", "full_name": "no_match" } } ] } ``` ## Returned data The exact fields surfaced in `source_data` depend on what the registry returns. The generated example for `deu_credit_bureau` currently documents this normalized shape: * `address` * `address_match_score` * `city` * `date_of_birth` * `first_name` * `full_name` * `last_name` * `name_match_score` * `postal_code` * `street` ## Pricing & SLAs Germany Credit Bureau queries are billed only when Didit receives a conclusive result from the validation source. * **Per-call price:** \$0.84 USD. * **Billing:** per successful query. You are not charged when the registry is unreachable, when required fields are missing, or when the request is rejected before reaching the source. * **Latency:** typical p95 \< 2 s. * **Availability:** 99.9% per quarter on Didit's side; downstream source availability varies by country and dataset. ## Continue reading * [Germany Database Validation overview](/api-reference/database-validation/germany) * [Database Validation overview](/core-technology/database-validation/overview) * [Outcome Codes](/core-technology/database-validation/database-validation-outcome-codes) # Germany Phone 2 Source: https://docs.didit.me/api-reference/database-validation/germany/phone-2 POST /v3/database-validation/ Verifies input data to mobile network operators phone data. Authoritative real-time identity lookup for Germany. Real-time lookup, pay-per-call.
Verifies input data to mobile network operators phone data. Didit exposes this service through `POST /v3/database-validation/` so you can verify the submitted data against the authoritative source and receive normalized match results. ## Coverage * **Coverage:** > 75% * **Country:** Germany * **Service ID:** `deu_phone_2` * **Data domain:** Telecom * **Category:** Telecom ## Inputs | Field | Required | Example | | --------------------- | -------: | ------------------- | | `first_name` | Yes | `John` | | `last_name` | Yes | `Doe` | | `address.street_1` | Yes | `123 Sample Street` | | `address.postal_code` | Yes | `10001` | | `phone` | Yes | `+15550101000` | | `date_of_birth` | No | `1990-01-01` | | `address.street_2` | No | `Unit 4` | | `address.city` | No | `Sample City` | | `address.region` | No | `Sample State` | | `vendor_data` | No | `user-1234` | * **Required inputs:** `first_name`, `last_name`, `address.street_1`, `address.postal_code`, `phone` * **Optional inputs:** `date_of_birth`, `address.street_2`, `address.city`, `address.region`, `vendor_data` * **Consent:** Not required * **Workflow availability:** Available in workflow * **Coverage:** > 75% * **Price:** \$0.59 per successful query ## Body parameters ISO 3166-1 alpha-3 country code for this database service. Example: `DEU` Array containing this service ID. Pinning the service keeps the request scoped to this exact database. Example: `deu_phone_2` Given name to validate. Example: `John` Family name to validate. Example: `Doe` Structured residential address object. Use `street_1`, `street_2`, `city`, `region`, `postal_code`, and `country`. A complete legacy address string is still accepted but not recommended. Example: `{"street_1":"123 Sample Street","street_2":"Unit 4","city":"Sample City","region":"Sample State","postal_code":"10001","country":"US"}` Phone number in international format. Example: `+15550101000` Date of birth in `YYYY-MM-DD` format. Example: `1990-01-01` Your stable user reference for this person, such as your internal user ID. Didit uses it to link standalone checks to the same end user and reduce duplicate-detection noise. Example: `user-1234` ## Input rules & validation notes * For address services, send structured address fields instead of a single `address` string when possible. * `address.street_1` is the street address, including street number and street type. * `address.street_2` is apartment, unit, building, floor, or extra address line. Send it only when you have it. * `address.city` is city, suburb, district, locality, or neighborhood. * `address.region` is state, province, region, or town. * `address.postal_code` is postcode or postal code. * Address-based database services require at least street address and postal code; requests rejected before source lookup are not charged. ## How to call it ```bash cURL theme={null} curl -X POST "https://verification.didit.me/v3/database-validation/" \ -H "x-api-key: YOUR_API_KEY" \ -F "issuing_state=DEU" \ -F "services=deu_phone_2" \ -F "vendor_data=user-1234" \ -F "first_name=John" \ -F "last_name=Doe" \ -F 'address={"street_1":"123 Sample Street","street_2":"Unit 4","city":"Sample City","region":"Sample State","postal_code":"10001","country":"US"}' \ -F "phone=+15550101000" ``` Every successful call returns HTTP `200`. The **`outcome_code`** field tells you what actually happened — distinguishing, for example, a real biometric mismatch (`BIOMETRIC_NO_MATCH`) from a selfie that could not be read (`BIOMETRIC_IMAGE_UNUSABLE`). The `status` shown is the default feature status; your configured [Partial Match / No Match actions](/core-technology/database-validation/database-validation-warnings) can override it. **`MATCH`** — The registry confirmed the identity and every checked field matched. ```json 200 OK — MATCH theme={null} { "request_id": "req_01H…", "status": "Approved", "issuing_state": "DEU", "match_type": "full_match", "validations": [ { "outcome_code": "MATCH", "service_id": "deu_phone_2", "service_name": "Germany Phone 2", "source_data": { "address": "123 Sample Street", "date_of_birth": "1990-01-01", "first_name": "John", "last_name": "Doe" }, "validation": { "address": "full_match", "full_name": "full_match" } } ] } ``` **`PARTIAL_MATCH`** — The identification number was found but one or more personal fields (usually name or date of birth) did not fully match. ```json 200 OK — PARTIAL_MATCH theme={null} { "request_id": "req_01H…", "status": "In Review", "issuing_state": "DEU", "match_type": "partial_match", "validations": [ { "outcome_code": "PARTIAL_MATCH", "service_id": "deu_phone_2", "service_name": "Germany Phone 2", "source_data": { "address": "123 Sample Street", "date_of_birth": "1990-01-01", "first_name": "John", "last_name": "Doe" }, "validation": { "address": "full_match", "full_name": "no_match" } } ] } ``` **`NO_MATCH`** — The registry returned no match for the submitted data. ```json 200 OK — NO_MATCH theme={null} { "request_id": "req_01H…", "status": "Declined", "issuing_state": "DEU", "match_type": "no_match", "validations": [ { "outcome_code": "NO_MATCH", "service_id": "deu_phone_2", "service_name": "Germany Phone 2", "source_data": { "address": "NO_MATCH", "full_name": "NO_MATCH" }, "validation": { "address": "no_match", "full_name": "no_match" } } ] } ``` ## Returned data The exact fields surfaced in `source_data` depend on what the registry returns. The generated example for `deu_phone_2` currently documents this normalized shape: * `address` * `date_of_birth` * `first_name` * `last_name` ## Pricing & SLAs Germany Phone 2 queries are billed only when Didit receives a conclusive result from the validation source. * **Per-call price:** \$0.59 USD. * **Billing:** per successful query. You are not charged when the registry is unreachable, when required fields are missing, or when the request is rejected before reaching the source. * **Latency:** typical p95 \< 2 s. * **Availability:** 99.9% per quarter on Didit's side; downstream source availability varies by country and dataset. ## Continue reading * [Germany Database Validation overview](/api-reference/database-validation/germany) * [Database Validation overview](/core-technology/database-validation/overview) * [Outcome Codes](/core-technology/database-validation/database-validation-outcome-codes) # Global - Identity Enrichment Source: https://docs.didit.me/api-reference/database-validation/global/identity-enrichment POST /v3/database-validation/ Resolves persons (names, DOB, addresses, phones, emails, national IDs) and a name-match score from an email and/or phone number via a global risk-insights network. Charged per request. Third-party identity-network lookup for Global. Real-time lookup, pay-per-call.
Resolves persons (names, DOB, addresses, phones, emails, national IDs) and a name-match score from an email and/or phone number via a global risk-insights network. Charged per request. Didit exposes this service through `POST /v3/database-validation/` so you can screen the submitted data against the connected identity network and receive normalized match results. This is a third-party enrichment network, not an authoritative government registry — do not present its results as primary-source verification. ## Coverage * **Coverage:** 50+ markets * **Country:** Global * **Service ID:** `glb_identity_enrichment` * **Data domain:** Identity * **Category:** IdentityEnrichment ## Inputs | Field | Required | Example | | ---------------------- | -------: | ---------------------- | | `email` | No | `john.doe@example.com` | | `phone` | No | `+15550101000` | | `first_name` | No | `John` | | `last_name` | No | `Doe` | | `full_name` | No | `John Doe` | | `country_of_residence` | No | `US` | | `vendor_data` | No | `user-1234` | * **Required inputs:** — * **Optional inputs:** `email`, `phone`, `first_name`, `last_name`, `full_name`, `country_of_residence`, `vendor_data` * **Consent:** Required * **Workflow availability:** Standalone API only * **Coverage:** 50+ markets * **Price:** \$0.20 per successful query This service needs an input no workflow step can produce (a biometric capture, a signed artifact, a live one-time code), so it is available only on the standalone API, where you supply the values directly. ## Body parameters ISO 3166-1 alpha-3 country code for this database service. Example: `GLB` Array containing this service ID. Pinning the service keeps the request scoped to this exact database. Example: `glb_identity_enrichment` Explicit end-user consent for this service. Example: `true` Email address. Example: `john.doe@example.com` Phone number in international format. Example: `+15550101000` Given name to validate. Example: `John` Family name to validate. Example: `Doe` Full legal name to validate. Example: `John Doe` Optional ISO 3166-1 alpha-2 country of residence. Only used to focus the identity lookup. Example: `US` Your stable user reference for this person, such as your internal user ID. Didit uses it to link standalone checks to the same end user and reduce duplicate-detection noise. Example: `user-1234` ## Input rules & validation notes * Provide at least one of `email` or `phone` - they are the lookup keys. A request with neither cannot perform an enrichment lookup and is rejected before source lookup (not charged). * Add `full_name` (or `first_name` + `last_name`) whenever you have it - the name is what the returned match score is computed against. * `country_of_residence` is an ISO 3166-1 alpha-2 code used to focus the lookup. * Every completed lookup is charged, including one that resolves no person at all (`persons_found: 0`). Only a request rejected before the lookup - neither `email` nor `phone` supplied - is free. ## How to call it ```bash cURL theme={null} curl -X POST "https://verification.didit.me/v3/database-validation/" \ -H "x-api-key: YOUR_API_KEY" \ -F "issuing_state=GLB" \ -F "services=glb_identity_enrichment" \ -F "vendor_data=user-1234" \ -F "consent=true" \ -F "email=john.doe@example.com" \ -F "phone=+15550101000" \ -F "full_name=John Doe" \ -F "country_of_residence=US" ``` Every successful call returns HTTP `200`. The **`outcome_code`** field tells you what actually happened — distinguishing, for example, a real biometric mismatch (`BIOMETRIC_NO_MATCH`) from a selfie that could not be read (`BIOMETRIC_IMAGE_UNUSABLE`). The `status` shown is the default feature status; your configured [Partial Match / No Match actions](/core-technology/database-validation/database-validation-warnings) can override it. **`MATCH`** — The registry confirmed the identity and every checked field matched. ```json 200 OK — MATCH theme={null} { "request_id": "req_01H…", "status": "Approved", "issuing_state": "GLB", "match_type": "full_match", "validations": [ { "outcome_code": "MATCH", "service_id": "glb_identity_enrichment", "service_name": "Global - Identity Enrichment", "source_data": { "first_name": "John", "full_name": "John Doe", "last_name": "Doe" }, "validation": { "identification_number": "full_match" } } ] } ``` **`PARTIAL_MATCH`** — The identification number was found but one or more personal fields (usually name or date of birth) did not fully match. ```json 200 OK — PARTIAL_MATCH theme={null} { "request_id": "req_01H…", "status": "In Review", "issuing_state": "GLB", "match_type": "partial_match", "validations": [ { "outcome_code": "PARTIAL_MATCH", "service_id": "glb_identity_enrichment", "service_name": "Global - Identity Enrichment", "source_data": { "first_name": "John", "full_name": "John Doe", "last_name": "Doe" }, "validation": { "identification_number": "no_match" } } ] } ``` **`NO_MATCH`** — The registry returned no match for the submitted data. ```json 200 OK — NO_MATCH theme={null} { "request_id": "req_01H…", "status": "Declined", "issuing_state": "GLB", "match_type": "no_match", "validations": [ { "outcome_code": "NO_MATCH", "service_id": "glb_identity_enrichment", "service_name": "Global - Identity Enrichment", "source_data": { "identification_number": "NO_MATCH" }, "validation": { "identification_number": "no_match" } } ] } ``` **`INCONCLUSIVE`** — The registry could not determine whether the person matches - the result is genuinely uncertain (they may or may not be in the registry). This is NOT a no-match and NOT a technical image problem; no field is asserted, so match\_type is null and the check is sent to review. ```json 200 OK — INCONCLUSIVE theme={null} { "request_id": "req_01H…", "status": "In Review", "issuing_state": "GLB", "match_type": null, "validations": [ { "outcome_code": "INCONCLUSIVE", "service_id": "glb_identity_enrichment", "service_name": "Global - Identity Enrichment", "source_data": {}, "validation": {} } ] } ``` **`DOCUMENT_NOT_FOUND`** — The submitted document number does not correspond to any record in the registry. ```json 200 OK — DOCUMENT_NOT_FOUND theme={null} { "request_id": "req_01H…", "status": "Declined", "issuing_state": "GLB", "match_type": "no_match", "validations": [ { "outcome_code": "DOCUMENT_NOT_FOUND", "service_id": "glb_identity_enrichment", "service_name": "Global - Identity Enrichment", "source_data": { "identification_number": "NO_MATCH" }, "validation": { "identification_number": "no_match" } } ] } ``` ## Returned data The exact fields surfaced in `source_data` depend on what the registry returns. The generated example for `glb_identity_enrichment` currently documents this normalized shape: * `first_name` * `full_name` * `last_name` ## Pricing & SLAs Global - Identity Enrichment queries are billed only when Didit receives a conclusive result from the validation source. * **Per-call price:** \$0.20 USD. * **Billing:** per successful query. You are not charged when the registry is unreachable, when required fields are missing, or when the request is rejected before reaching the source. * **Latency:** typical p95 \< 2 s. * **Availability:** 99.9% per quarter on Didit's side; downstream source availability varies by country and dataset. ## Continue reading * [Global Database Validation overview](/getting-started/database-validation-pricing) * [Database Validation overview](/core-technology/database-validation/overview) * [Outcome Codes](/core-technology/database-validation/database-validation-outcome-codes) # Global - Core Intelligence Service Source: https://docs.didit.me/api-reference/database-validation/global/intelligence-service POST /v3/database-validation/ Performs a series of checks across multiple data partners and returns risks associated with each data point. Authoritative real-time identity lookup for Global. Real-time lookup, pay-per-call.
Performs a series of checks across multiple data partners and returns risks associated with each data point. Didit exposes this service through `POST /v3/database-validation/` so you can verify the submitted data against the authoritative source and receive normalized match results. ## Coverage * **Coverage:** — * **Country:** Global * **Service ID:** `glb_intelligence_service` * **Data domain:** Telecom * **Category:** Telecom ## Inputs | Field | Required | Example | | ------------- | -------: | -------------- | | `phone` | Yes | `+15550101000` | | `vendor_data` | No | `user-1234` | * **Required inputs:** `phone` * **Optional inputs:** `vendor_data` * **Consent:** Not required * **Workflow availability:** Available in workflow * **Coverage:** — * **Price:** \$0.41 per successful query ## Body parameters ISO 3166-1 alpha-3 country code for this database service. Example: `GLB` Array containing this service ID. Pinning the service keeps the request scoped to this exact database. Example: `glb_intelligence_service` Phone number in international format. Example: `+15550101000` Your stable user reference for this person, such as your internal user ID. Didit uses it to link standalone checks to the same end user and reduce duplicate-detection noise. Example: `user-1234` ## Input rules & validation notes * Send the fields listed above exactly as captured from the user or document. * Didit validates required fields before calling the database. Requests rejected before source lookup are not charged. ## How to call it ```bash cURL theme={null} curl -X POST "https://verification.didit.me/v3/database-validation/" \ -H "x-api-key: YOUR_API_KEY" \ -F "issuing_state=GLB" \ -F "services=glb_intelligence_service" \ -F "vendor_data=user-1234" \ -F "phone=+15550101000" ``` Every successful call returns HTTP `200`. The **`outcome_code`** field tells you what actually happened — distinguishing, for example, a real biometric mismatch (`BIOMETRIC_NO_MATCH`) from a selfie that could not be read (`BIOMETRIC_IMAGE_UNUSABLE`). The `status` shown is the default feature status; your configured [Partial Match / No Match actions](/core-technology/database-validation/database-validation-warnings) can override it. **`MATCH`** — The registry confirmed the identity and every checked field matched. ```json 200 OK — MATCH theme={null} { "request_id": "req_01H…", "status": "Approved", "issuing_state": "GLB", "match_type": "full_match", "validations": [ { "outcome_code": "MATCH", "service_id": "glb_intelligence_service", "service_name": "Global - Core Intelligence Service", "source_data": {}, "validation": { "identification_number": "full_match" } } ] } ``` **`NO_MATCH`** — The registry returned no match for the submitted data. ```json 200 OK — NO_MATCH theme={null} { "request_id": "req_01H…", "status": "Declined", "issuing_state": "GLB", "match_type": "no_match", "validations": [ { "outcome_code": "NO_MATCH", "service_id": "glb_intelligence_service", "service_name": "Global - Core Intelligence Service", "source_data": { "identification_number": "NO_MATCH" }, "validation": { "identification_number": "no_match" } } ] } ``` ## Returned data The exact fields surfaced in `source_data` depend on what the registry returns. The generated example for `glb_intelligence_service` currently documents this normalized shape: * Varies by registry response. ## Pricing & SLAs Global - Core Intelligence Service queries are billed only when Didit receives a conclusive result from the validation source. * **Per-call price:** \$0.41 USD. * **Billing:** per successful query. You are not charged when the registry is unreachable, when required fields are missing, or when the request is rejected before reaching the source. * **Latency:** typical p95 \< 2 s. * **Availability:** 99.9% per quarter on Didit's side; downstream source availability varies by country and dataset. ## Continue reading * [Global Database Validation overview](/getting-started/database-validation-pricing) * [Database Validation overview](/core-technology/database-validation/overview) * [Outcome Codes](/core-technology/database-validation/database-validation-outcome-codes) # Global - Sim Swap Source: https://docs.didit.me/api-reference/database-validation/global/swap POST /v3/database-validation/ Returns data points associated with any Sim Swap activity on the input phone number. Authoritative real-time identity lookup for Global. Real-time lookup, pay-per-call.
Returns data points associated with any Sim Swap activity on the input phone number. Didit exposes this service through `POST /v3/database-validation/` so you can verify the submitted data against the authoritative source and receive normalized match results. ## Coverage * **Coverage:** — * **Country:** Global * **Service ID:** `glb_swap` * **Data domain:** Telecom * **Category:** Telecom ## Inputs | Field | Required | Example | | ------------- | -------: | -------------- | | `phone` | Yes | `+15550101000` | | `vendor_data` | No | `user-1234` | * **Required inputs:** `phone` * **Optional inputs:** `vendor_data` * **Consent:** Not required * **Workflow availability:** Available in workflow * **Coverage:** — * **Price:** \$0.18 per successful query ## Body parameters ISO 3166-1 alpha-3 country code for this database service. Example: `GLB` Array containing this service ID. Pinning the service keeps the request scoped to this exact database. Example: `glb_swap` Phone number in international format. Example: `+15550101000` Your stable user reference for this person, such as your internal user ID. Didit uses it to link standalone checks to the same end user and reduce duplicate-detection noise. Example: `user-1234` ## Input rules & validation notes * Send the fields listed above exactly as captured from the user or document. * Didit validates required fields before calling the database. Requests rejected before source lookup are not charged. ## How to call it ```bash cURL theme={null} curl -X POST "https://verification.didit.me/v3/database-validation/" \ -H "x-api-key: YOUR_API_KEY" \ -F "issuing_state=GLB" \ -F "services=glb_swap" \ -F "vendor_data=user-1234" \ -F "phone=+15550101000" ``` Every successful call returns HTTP `200`. The **`outcome_code`** field tells you what actually happened — distinguishing, for example, a real biometric mismatch (`BIOMETRIC_NO_MATCH`) from a selfie that could not be read (`BIOMETRIC_IMAGE_UNUSABLE`). The `status` shown is the default feature status; your configured [Partial Match / No Match actions](/core-technology/database-validation/database-validation-warnings) can override it. **`MATCH`** — The registry confirmed the identity and every checked field matched. ```json 200 OK — MATCH theme={null} { "request_id": "req_01H…", "status": "Approved", "issuing_state": "GLB", "match_type": "full_match", "validations": [ { "outcome_code": "MATCH", "service_id": "glb_swap", "service_name": "Global - Sim Swap", "source_data": {}, "validation": { "identification_number": "full_match" } } ] } ``` **`NO_MATCH`** — The registry returned no match for the submitted data. ```json 200 OK — NO_MATCH theme={null} { "request_id": "req_01H…", "status": "Declined", "issuing_state": "GLB", "match_type": "no_match", "validations": [ { "outcome_code": "NO_MATCH", "service_id": "glb_swap", "service_name": "Global - Sim Swap", "source_data": { "identification_number": "NO_MATCH" }, "validation": { "identification_number": "no_match" } } ] } ``` ## Returned data The exact fields surfaced in `source_data` depend on what the registry returns. The generated example for `glb_swap` currently documents this normalized shape: * Varies by registry response. ## Pricing & SLAs Global - Sim Swap queries are billed only when Didit receives a conclusive result from the validation source. * **Per-call price:** \$0.18 USD. * **Billing:** per successful query. You are not charged when the registry is unreachable, when required fields are missing, or when the request is rejected before reaching the source. * **Latency:** typical p95 \< 2 s. * **Availability:** 99.9% per quarter on Didit's side; downstream source availability varies by country and dataset. ## Continue reading * [Global Database Validation overview](/getting-started/database-validation-pricing) * [Database Validation overview](/core-technology/database-validation/overview) * [Outcome Codes](/core-technology/database-validation/database-validation-outcome-codes) # Guatemala - DPI verification Source: https://docs.didit.me/api-reference/database-validation/guatemala/dpi POST /v3/database-validation/ Verifies Guatemalan unique identification code data against SAT government records. Authoritative real-time identity lookup for Guatemala. Real-time lookup, pay-per-call.
Verifies Guatemalan unique identification code data against SAT government records. Didit exposes this service through `POST /v3/database-validation/` so you can verify the submitted data against the authoritative source and receive normalized match results. ## Coverage * **Coverage:** 90-95% * **Country:** Guatemala * **Service ID:** `gtm_dpi` * **Data domain:** Identity * **Category:** NationalIDRegistry ## Inputs | Field | Required | Example | | ----------------- | -------: | --------------- | | `document_number` | Yes | `1111111111111` | | `date_of_birth` | Yes | `1990-01-01` | | `first_name` | No | `John` | | `last_name` | No | `Doe` | | `vendor_data` | No | `user-1234` | * **Required inputs:** `document_number`, `date_of_birth` * **Optional inputs:** `first_name`, `last_name`, `vendor_data` * **Consent:** Not required * **Workflow availability:** Available in workflow * **Coverage:** 90-95% * **Price:** \$0.20 per successful query ## Body parameters ISO 3166-1 alpha-3 country code for this database service. Example: `GTM` Array containing this service ID. Pinning the service keeps the request scoped to this exact database. Example: `gtm_dpi` Document number extracted from or provided by the user. Example: `1111111111111` Date of birth in `YYYY-MM-DD` format. Example: `1990-01-01` Given name to validate. Example: `John` Family name to validate. Example: `Doe` Your stable user reference for this person, such as your internal user ID. Didit uses it to link standalone checks to the same end user and reduce duplicate-detection noise. Example: `user-1234` ## Input rules & validation notes * Guatemalan DPI (exactly 13 digits) * `document_number` must contain digits only; remove spaces, hyphens, and punctuation before sending the request. * `document_number` must be exactly 13 characters long. ## How to call it ```bash cURL theme={null} curl -X POST "https://verification.didit.me/v3/database-validation/" \ -H "x-api-key: YOUR_API_KEY" \ -F "issuing_state=GTM" \ -F "services=gtm_dpi" \ -F "vendor_data=user-1234" \ -F "document_number=1111111111111" \ -F "date_of_birth=1990-01-01" ``` Every successful call returns HTTP `200`. The **`outcome_code`** field tells you what actually happened — distinguishing, for example, a real biometric mismatch (`BIOMETRIC_NO_MATCH`) from a selfie that could not be read (`BIOMETRIC_IMAGE_UNUSABLE`). The `status` shown is the default feature status; your configured [Partial Match / No Match actions](/core-technology/database-validation/database-validation-warnings) can override it. **`MATCH`** — The registry confirmed the identity and every checked field matched. ```json 200 OK — MATCH theme={null} { "request_id": "req_01H…", "status": "Approved", "issuing_state": "GTM", "match_type": "full_match", "validations": [ { "outcome_code": "MATCH", "service_id": "gtm_dpi", "service_name": "Guatemala - DPI verification", "source_data": { "first_name": "John", "full_name": "John Doe", "identification_number": "SAMPLE-ID-12345", "last_name": "Doe" }, "validation": { "date_of_birth": "full_match", "identification_number": "full_match" } } ] } ``` **`PARTIAL_MATCH`** — The identification number was found but one or more personal fields (usually name or date of birth) did not fully match. ```json 200 OK — PARTIAL_MATCH theme={null} { "request_id": "req_01H…", "status": "In Review", "issuing_state": "GTM", "match_type": "partial_match", "validations": [ { "outcome_code": "PARTIAL_MATCH", "service_id": "gtm_dpi", "service_name": "Guatemala - DPI verification", "source_data": { "first_name": "John", "full_name": "John Doe", "identification_number": "SAMPLE-ID-12345", "last_name": "Doe" }, "validation": { "date_of_birth": "no_match", "identification_number": "full_match" } } ] } ``` **`NO_MATCH`** — The registry returned no match for the submitted data. ```json 200 OK — NO_MATCH theme={null} { "request_id": "req_01H…", "status": "Declined", "issuing_state": "GTM", "match_type": "no_match", "validations": [ { "outcome_code": "NO_MATCH", "service_id": "gtm_dpi", "service_name": "Guatemala - DPI verification", "source_data": { "date_of_birth": "NO_MATCH", "identification_number": "NO_MATCH" }, "validation": { "date_of_birth": "no_match", "identification_number": "no_match" } } ] } ``` ## Returned data The exact fields surfaced in `source_data` depend on what the registry returns. The generated example for `gtm_dpi` currently documents this normalized shape: * `first_name` * `full_name` * `identification_number` * `last_name` ## Pricing & SLAs Guatemala - DPI verification queries are billed only when Didit receives a conclusive result from the validation source. * **Per-call price:** \$0.20 USD. * **Billing:** per successful query. You are not charged when the registry is unreachable, when required fields are missing, or when the request is rejected before reaching the source. * **Latency:** typical p95 \< 2 s. * **Availability:** 99.9% per quarter on Didit's side; downstream source availability varies by country and dataset. ## Continue reading * [Guatemala Database Validation overview](/api-reference/database-validation/guatemala) * [Database Validation overview](/core-technology/database-validation/overview) * [Outcome Codes](/core-technology/database-validation/database-validation-outcome-codes) # Honduras - DNI verification Source: https://docs.didit.me/api-reference/database-validation/honduras/dni POST /v3/database-validation/ Verifies Honduran DNI data against CNE electoral registry records. Authoritative real-time identity lookup for Honduras. Real-time lookup, pay-per-call.
Verifies Honduran DNI data against CNE electoral registry records. Didit exposes this service through `POST /v3/database-validation/` so you can verify the submitted data against the authoritative source and receive normalized match results. ## Coverage * **Coverage:** 90-95% * **Country:** Honduras * **Service ID:** `hnd_dni` * **Data domain:** Identity * **Category:** NationalIDRegistry ## Inputs | Field | Required | Example | | ----------------- | -------: | --------------- | | `document_number` | Yes | `1111111111111` | | `first_name` | No | `John` | | `last_name` | No | `Doe` | | `vendor_data` | No | `user-1234` | * **Required inputs:** `document_number` * **Optional inputs:** `first_name`, `last_name`, `vendor_data` * **Consent:** Not required * **Workflow availability:** Available in workflow * **Coverage:** 90-95% * **Price:** \$0.20 per successful query ## Body parameters ISO 3166-1 alpha-3 country code for this database service. Example: `HND` Array containing this service ID. Pinning the service keeps the request scoped to this exact database. Example: `hnd_dni` Document number extracted from or provided by the user. Example: `1111111111111` Given name to validate. Example: `John` Family name to validate. Example: `Doe` Your stable user reference for this person, such as your internal user ID. Didit uses it to link standalone checks to the same end user and reduce duplicate-detection noise. Example: `user-1234` ## Input rules & validation notes * Honduran DNI (exactly 13 digits) * `document_number` must contain digits only; remove spaces, hyphens, and punctuation before sending the request. * `document_number` must be exactly 13 characters long. ## How to call it ```bash cURL theme={null} curl -X POST "https://verification.didit.me/v3/database-validation/" \ -H "x-api-key: YOUR_API_KEY" \ -F "issuing_state=HND" \ -F "services=hnd_dni" \ -F "vendor_data=user-1234" \ -F "document_number=1111111111111" ``` Every successful call returns HTTP `200`. The **`outcome_code`** field tells you what actually happened — distinguishing, for example, a real biometric mismatch (`BIOMETRIC_NO_MATCH`) from a selfie that could not be read (`BIOMETRIC_IMAGE_UNUSABLE`). The `status` shown is the default feature status; your configured [Partial Match / No Match actions](/core-technology/database-validation/database-validation-warnings) can override it. **`MATCH`** — The registry confirmed the identity and every checked field matched. ```json 200 OK — MATCH theme={null} { "request_id": "req_01H…", "status": "Approved", "issuing_state": "HND", "match_type": "full_match", "validations": [ { "outcome_code": "MATCH", "service_id": "hnd_dni", "service_name": "Honduras - DNI verification", "source_data": { "document_type": "sample_value", "first_name": "John", "full_name": "John Doe", "identification_number": "SAMPLE-ID-12345", "last_name": "Doe" }, "validation": { "identification_number": "full_match" } } ] } ``` **`NO_MATCH`** — The registry returned no match for the submitted data. ```json 200 OK — NO_MATCH theme={null} { "request_id": "req_01H…", "status": "Declined", "issuing_state": "HND", "match_type": "no_match", "validations": [ { "outcome_code": "NO_MATCH", "service_id": "hnd_dni", "service_name": "Honduras - DNI verification", "source_data": { "identification_number": "NO_MATCH" }, "validation": { "identification_number": "no_match" } } ] } ``` ## Returned data The exact fields surfaced in `source_data` depend on what the registry returns. The generated example for `hnd_dni` currently documents this normalized shape: * `document_type` * `first_name` * `full_name` * `identification_number` * `last_name` ## Pricing & SLAs Honduras - DNI verification queries are billed only when Didit receives a conclusive result from the validation source. * **Per-call price:** \$0.20 USD. * **Billing:** per successful query. You are not charged when the registry is unreachable, when required fields are missing, or when the request is rejected before reaching the source. * **Latency:** typical p95 \< 2 s. * **Availability:** 99.9% per quarter on Didit's side; downstream source availability varies by country and dataset. ## Continue reading * [Honduras Database Validation overview](/api-reference/database-validation/honduras) * [Database Validation overview](/core-technology/database-validation/overview) * [Outcome Codes](/core-technology/database-validation/database-validation-outcome-codes) # India Aadhaar (UIDAI) Source: https://docs.didit.me/api-reference/database-validation/india/aadhaar POST /v3/database-validation/ Verifies the input Aadhaar number against UIDAI identity records. Authoritative real-time identity lookup for India. Real-time lookup, pay-per-call.
Verifies the input Aadhaar number against UIDAI identity records. Didit exposes this service through `POST /v3/database-validation/` so you can verify the submitted data against the authoritative source and receive normalized match results. ## Coverage * **Coverage:** \~ 100% * **Country:** India * **Service ID:** `ind_aadhaar` * **Data domain:** Identity * **Category:** NationalIDRegistry ## Inputs | Field | Required | Example | | ----------------- | -------: | -------------- | | `full_name` | Yes | `John Doe` | | `date_of_birth` | Yes | `1990-01-01` | | `personal_number` | Yes | `111111111111` | | `pan` | Yes | `ABCDE1234F` | | `vendor_data` | No | `user-1234` | * **Required inputs:** `full_name`, `date_of_birth`, `personal_number`, `pan` * **Optional inputs:** `vendor_data` * **Consent:** Required * **Workflow availability:** Available in workflow * **Coverage:** \~ 100% * **Price:** \$0.25 per successful query Not every document this service accepts carries the identifier it queries by. When the identifier is not extracted from the document the check is recorded as **not applicable** - no database is queried and you are not charged - which for some countries is a large share of real users. To cover them, also collect the identifier from a Questionnaire answer, a Document AI extraction field, or a value you send when you create the session, and map it on the Database Validation step. ## Body parameters ISO 3166-1 alpha-3 country code for this database service. Example: `IND` Array containing this service ID. Pinning the service keeps the request scoped to this exact database. Example: `ind_aadhaar` Explicit end-user consent for this service. Example: `true` Full legal name to validate. Example: `John Doe` Date of birth in `YYYY-MM-DD` format. Example: `1990-01-01` Country-specific personal identity number. Example: `111111111111` Permanent Account Number. Example: `ABCDE1234F` Your stable user reference for this person, such as your internal user ID. Didit uses it to link standalone checks to the same end user and reduce duplicate-detection noise. Example: `user-1234` ## Input rules & validation notes * `pan` must use uppercase letters. * `pan` must match `[A-Z]{5}\d{4}[A-Z]`. * `personal_number` must contain digits only; remove spaces, hyphens, and punctuation before sending the request. * `personal_number` must be exactly 12 characters long. ## How to call it ```bash cURL theme={null} curl -X POST "https://verification.didit.me/v3/database-validation/" \ -H "x-api-key: YOUR_API_KEY" \ -F "issuing_state=IND" \ -F "services=ind_aadhaar" \ -F "vendor_data=user-1234" \ -F "consent=true" \ -F "full_name=John Doe" \ -F "date_of_birth=1990-01-01" \ -F "personal_number=111111111111" \ -F "pan=ABCDE1234F" ``` Every successful call returns HTTP `200`. The **`outcome_code`** field tells you what actually happened — distinguishing, for example, a real biometric mismatch (`BIOMETRIC_NO_MATCH`) from a selfie that could not be read (`BIOMETRIC_IMAGE_UNUSABLE`). The `status` shown is the default feature status; your configured [Partial Match / No Match actions](/core-technology/database-validation/database-validation-warnings) can override it. **`MATCH`** — The registry confirmed the identity and every checked field matched. ```json 200 OK — MATCH theme={null} { "request_id": "req_01H…", "status": "Approved", "issuing_state": "IND", "match_type": "full_match", "validations": [ { "outcome_code": "MATCH", "service_id": "ind_aadhaar", "service_name": "India Aadhaar (UIDAI)", "source_data": { "date_of_birth": "1990-01-01", "full_name": "John Doe", "identification_number": "SAMPLE-ID-12345" }, "validation": { "date_of_birth": "full_match", "full_name": "full_match", "identification_number": "full_match" } } ] } ``` **`PARTIAL_MATCH`** — The identification number was found but one or more personal fields (usually name or date of birth) did not fully match. ```json 200 OK — PARTIAL_MATCH theme={null} { "request_id": "req_01H…", "status": "In Review", "issuing_state": "IND", "match_type": "partial_match", "validations": [ { "outcome_code": "PARTIAL_MATCH", "service_id": "ind_aadhaar", "service_name": "India Aadhaar (UIDAI)", "source_data": { "date_of_birth": "1990-01-01", "full_name": "John Doe", "identification_number": "SAMPLE-ID-12345" }, "validation": { "date_of_birth": "full_match", "full_name": "no_match", "identification_number": "full_match" } } ] } ``` **`NO_MATCH`** — The registry returned no match for the submitted data. ```json 200 OK — NO_MATCH theme={null} { "request_id": "req_01H…", "status": "Declined", "issuing_state": "IND", "match_type": "no_match", "validations": [ { "outcome_code": "NO_MATCH", "service_id": "ind_aadhaar", "service_name": "India Aadhaar (UIDAI)", "source_data": { "date_of_birth": "NO_MATCH", "full_name": "NO_MATCH", "identification_number": "NO_MATCH" }, "validation": { "date_of_birth": "no_match", "full_name": "no_match", "identification_number": "no_match" } } ] } ``` ## Returned data The exact fields surfaced in `source_data` depend on what the registry returns. The generated example for `ind_aadhaar` currently documents this normalized shape: * `date_of_birth` * `full_name` * `identification_number` ## Pricing & SLAs India Aadhaar (UIDAI) queries are billed only when Didit receives a conclusive result from the validation source. * **Per-call price:** \$0.25 USD. * **Billing:** per successful query. You are not charged when the registry is unreachable, when required fields are missing, or when the request is rejected before reaching the source. * **Latency:** typical p95 \< 2 s. * **Availability:** 99.9% per quarter on Didit's side; downstream source availability varies by country and dataset. ## Continue reading * [India Database Validation overview](/api-reference/database-validation/india) * [Database Validation overview](/core-technology/database-validation/overview) * [Outcome Codes](/core-technology/database-validation/database-validation-outcome-codes) # India Drivers Licence (RTO) Source: https://docs.didit.me/api-reference/database-validation/india/drivers-licence POST /v3/database-validation/ Verifies input data against the databases of the Road Transport Offices of the States of India. Authoritative real-time identity lookup for India. Real-time lookup, pay-per-call.
Verifies input data against the databases of the Road Transport Offices of the States of India. Didit exposes this service through `POST /v3/database-validation/` so you can verify the submitted data against the authoritative source and receive normalized match results. ## Coverage * **Coverage:** > 75% * **Country:** India * **Service ID:** `ind_drivers_licence` * **Data domain:** Document * **Category:** DriverLicence ## Inputs | Field | Required | Example | | ----------------------- | -------: | ------------------- | | `full_name` | Yes | `John Doe` | | `date_of_birth` | Yes | `1990-01-01` | | `driver_license_number` | Yes | `SAMPLE-DL-12345` | | `address.street_1` | No | `123 Sample Street` | | `address.street_2` | No | `Unit 4` | | `address.city` | No | `Sample City` | | `address.region` | No | `Sample State` | | `address.postal_code` | No | `10001` | | `vendor_data` | No | `user-1234` | * **Required inputs:** `full_name`, `date_of_birth`, `driver_license_number` * **Optional inputs:** `address.street_1`, `address.street_2`, `address.city`, `address.region`, `address.postal_code`, `vendor_data` * **Consent:** Required * **Workflow availability:** Available in workflow * **Coverage:** > 75% * **Price:** \$0.15 per successful query ## Body parameters ISO 3166-1 alpha-3 country code for this database service. Example: `IND` Array containing this service ID. Pinning the service keeps the request scoped to this exact database. Example: `ind_drivers_licence` Explicit end-user consent for this service. Example: `true` Full legal name to validate. Example: `John Doe` Date of birth in `YYYY-MM-DD` format. Example: `1990-01-01` Driver licence number. Example: `SAMPLE-DL-12345` Structured residential address object. Use `street_1`, `street_2`, `city`, `region`, `postal_code`, and `country`. A complete legacy address string is still accepted but not recommended. Example: `{"street_1":"123 Sample Street","street_2":"Unit 4","city":"Sample City","region":"Sample State","postal_code":"10001","country":"US"}` Your stable user reference for this person, such as your internal user ID. Didit uses it to link standalone checks to the same end user and reduce duplicate-detection noise. Example: `user-1234` ## Input rules & validation notes * `address` is optional for this service. You can send one complete `address` string and Didit will split it into structured address elements when possible, or you can send the structured fields explicitly. * For address services, send structured address fields instead of a single `address` string when possible. * `address.street_1` is the street address, including street number and street type. * `address.street_2` is apartment, unit, building, floor, or extra address line. Send it only when you have it. * `address.city` is city, suburb, district, locality, or neighborhood. * `address.region` is state, province, region, or town. * `address.postal_code` is postcode or postal code. * Address-based database services require at least street address and postal code; requests rejected before source lookup are not charged. ## How to call it ```bash cURL theme={null} curl -X POST "https://verification.didit.me/v3/database-validation/" \ -H "x-api-key: YOUR_API_KEY" \ -F "issuing_state=IND" \ -F "services=ind_drivers_licence" \ -F "vendor_data=user-1234" \ -F "consent=true" \ -F "full_name=John Doe" \ -F "date_of_birth=1990-01-01" \ -F "driver_license_number=SAMPLE-DL-12345" ``` Every successful call returns HTTP `200`. The **`outcome_code`** field tells you what actually happened — distinguishing, for example, a real biometric mismatch (`BIOMETRIC_NO_MATCH`) from a selfie that could not be read (`BIOMETRIC_IMAGE_UNUSABLE`). The `status` shown is the default feature status; your configured [Partial Match / No Match actions](/core-technology/database-validation/database-validation-warnings) can override it. **`MATCH`** — The registry confirmed the identity and every checked field matched. ```json 200 OK — MATCH theme={null} { "request_id": "req_01H…", "status": "Approved", "issuing_state": "IND", "match_type": "full_match", "validations": [ { "outcome_code": "MATCH", "service_id": "ind_drivers_licence", "service_name": "India Drivers Licence (RTO)", "source_data": { "address": "123 Sample Street", "address_match_score": "1.000", "date_of_birth": "1990-01-01", "identification_number": "SAMPLE-ID-12345", "verifications": { "date_of_birth": true, "full_name": true, "identification_number": true } }, "validation": { "date_of_birth": "full_match", "full_name": "full_match", "identification_number": "full_match" } } ] } ``` **`PARTIAL_MATCH`** — The identification number was found but one or more personal fields (usually name or date of birth) did not fully match. ```json 200 OK — PARTIAL_MATCH theme={null} { "request_id": "req_01H…", "status": "In Review", "issuing_state": "IND", "match_type": "partial_match", "validations": [ { "outcome_code": "PARTIAL_MATCH", "service_id": "ind_drivers_licence", "service_name": "India Drivers Licence (RTO)", "source_data": { "address": "123 Sample Street", "address_match_score": "1.000", "date_of_birth": "1990-01-01", "identification_number": "SAMPLE-ID-12345", "verifications": { "date_of_birth": true, "full_name": false, "identification_number": true } }, "validation": { "date_of_birth": "full_match", "full_name": "no_match", "identification_number": "full_match" } } ] } ``` **`NO_MATCH`** — The registry returned no match for the submitted data. ```json 200 OK — NO_MATCH theme={null} { "request_id": "req_01H…", "status": "Declined", "issuing_state": "IND", "match_type": "no_match", "validations": [ { "outcome_code": "NO_MATCH", "service_id": "ind_drivers_licence", "service_name": "India Drivers Licence (RTO)", "source_data": { "date_of_birth": "NO_MATCH", "full_name": "NO_MATCH", "identification_number": "NO_MATCH" }, "validation": { "date_of_birth": "no_match", "full_name": "no_match", "identification_number": "no_match" } } ] } ``` ## Returned data The exact fields surfaced in `source_data` depend on what the registry returns. The generated example for `ind_drivers_licence` currently documents this normalized shape: * `address` * `address_match_score` * `date_of_birth` * `identification_number` ## Pricing & SLAs India Drivers Licence (RTO) queries are billed only when Didit receives a conclusive result from the validation source. * **Per-call price:** \$0.15 USD. * **Billing:** per successful query. You are not charged when the registry is unreachable, when required fields are missing, or when the request is rejected before reaching the source. * **Latency:** typical p95 \< 2 s. * **Availability:** 99.9% per quarter on Didit's side; downstream source availability varies by country and dataset. ## Continue reading * [India Database Validation overview](/api-reference/database-validation/india) * [Database Validation overview](/core-technology/database-validation/overview) * [Outcome Codes](/core-technology/database-validation/database-validation-outcome-codes) # India EPIC (Voter's Registration) (ECI) Source: https://docs.didit.me/api-reference/database-validation/india/epic-voter-s-registration POST /v3/database-validation/ Verifies input data against the Election Commission of India database. Authoritative real-time identity lookup for India. Real-time lookup, pay-per-call.
Verifies input data against the Election Commission of India database. Didit exposes this service through `POST /v3/database-validation/` so you can verify the submitted data against the authoritative source and receive normalized match results. ## Coverage * **Coverage:** > 75% * **Country:** India * **Service ID:** `ind_epic_voter_s_registration` * **Data domain:** Government * **Category:** ElectoralRoll ## Inputs | Field | Required | Example | | --------------- | -------: | ------------ | | `full_name` | Yes | `John Doe` | | `date_of_birth` | Yes | `1990-01-01` | | `epic_card` | Yes | `ABC1234567` | | `vendor_data` | No | `user-1234` | * **Required inputs:** `full_name`, `date_of_birth`, `epic_card` * **Optional inputs:** `vendor_data` * **Consent:** Required * **Workflow availability:** Available in workflow with field mapping * **Coverage:** > 75% * **Price:** \$0.15 per successful query In a workflow, `epic_card` is not printed on an identity document, so no step produces it on its own. Collect it from a Questionnaire answer, a Document AI extraction field, or a value you send when you create the session, and map it on the Database Validation step. Until it is mapped the workflow editor shows this service disabled and names the missing input; at run time a missing input means the check is skipped before any query, so you are never billed for a database that could not be asked. Not every document this service accepts carries the identifier it queries by. When the identifier is not extracted from the document the check is recorded as **not applicable** - no database is queried and you are not charged - which for some countries is a large share of real users. To cover them, also collect the identifier from a Questionnaire answer, a Document AI extraction field, or a value you send when you create the session, and map it on the Database Validation step. ## Body parameters ISO 3166-1 alpha-3 country code for this database service. Example: `IND` Array containing this service ID. Pinning the service keeps the request scoped to this exact database. Example: `ind_epic_voter_s_registration` Explicit end-user consent for this service. Example: `true` Full legal name to validate. Example: `John Doe` Date of birth in `YYYY-MM-DD` format. Example: `1990-01-01` EPIC voter card number. Example: `ABC1234567` Your stable user reference for this person, such as your internal user ID. Didit uses it to link standalone checks to the same end user and reduce duplicate-detection noise. Example: `user-1234` ## Input rules & validation notes * `epic_card` must match `[A-Za-z]{3}\d{7,14}`. ## How to call it ```bash cURL theme={null} curl -X POST "https://verification.didit.me/v3/database-validation/" \ -H "x-api-key: YOUR_API_KEY" \ -F "issuing_state=IND" \ -F "services=ind_epic_voter_s_registration" \ -F "vendor_data=user-1234" \ -F "consent=true" \ -F "full_name=John Doe" \ -F "date_of_birth=1990-01-01" \ -F "epic_card=ABC1234567" ``` Every successful call returns HTTP `200`. The **`outcome_code`** field tells you what actually happened — distinguishing, for example, a real biometric mismatch (`BIOMETRIC_NO_MATCH`) from a selfie that could not be read (`BIOMETRIC_IMAGE_UNUSABLE`). The `status` shown is the default feature status; your configured [Partial Match / No Match actions](/core-technology/database-validation/database-validation-warnings) can override it. **`MATCH`** — The registry confirmed the identity and every checked field matched. ```json 200 OK — MATCH theme={null} { "request_id": "req_01H…", "status": "Approved", "issuing_state": "IND", "match_type": "full_match", "validations": [ { "outcome_code": "MATCH", "service_id": "ind_epic_voter_s_registration", "service_name": "India EPIC (Voter's Registration) (ECI)", "source_data": { "date_of_birth": "1990-01-01", "full_name": "John Doe", "identification_number": "SAMPLE-ID-12345" }, "validation": { "date_of_birth": "full_match", "full_name": "full_match", "identification_number": "full_match" } } ] } ``` **`PARTIAL_MATCH`** — The identification number was found but one or more personal fields (usually name or date of birth) did not fully match. ```json 200 OK — PARTIAL_MATCH theme={null} { "request_id": "req_01H…", "status": "In Review", "issuing_state": "IND", "match_type": "partial_match", "validations": [ { "outcome_code": "PARTIAL_MATCH", "service_id": "ind_epic_voter_s_registration", "service_name": "India EPIC (Voter's Registration) (ECI)", "source_data": { "date_of_birth": "1990-01-01", "full_name": "John Doe", "identification_number": "SAMPLE-ID-12345" }, "validation": { "date_of_birth": "full_match", "full_name": "no_match", "identification_number": "full_match" } } ] } ``` **`NO_MATCH`** — The registry returned no match for the submitted data. ```json 200 OK — NO_MATCH theme={null} { "request_id": "req_01H…", "status": "Declined", "issuing_state": "IND", "match_type": "no_match", "validations": [ { "outcome_code": "NO_MATCH", "service_id": "ind_epic_voter_s_registration", "service_name": "India EPIC (Voter's Registration) (ECI)", "source_data": { "date_of_birth": "NO_MATCH", "full_name": "NO_MATCH", "identification_number": "NO_MATCH" }, "validation": { "date_of_birth": "no_match", "full_name": "no_match", "identification_number": "no_match" } } ] } ``` ## Returned data The exact fields surfaced in `source_data` depend on what the registry returns. The generated example for `ind_epic_voter_s_registration` currently documents this normalized shape: * `date_of_birth` * `full_name` * `identification_number` ## Pricing & SLAs India EPIC (Voter's Registration) (ECI) queries are billed only when Didit receives a conclusive result from the validation source. * **Per-call price:** \$0.15 USD. * **Billing:** per successful query. You are not charged when the registry is unreachable, when required fields are missing, or when the request is rejected before reaching the source. * **Latency:** typical p95 \< 2 s. * **Availability:** 99.9% per quarter on Didit's side; downstream source availability varies by country and dataset. ## Continue reading * [India Database Validation overview](/api-reference/database-validation/india) * [Database Validation overview](/core-technology/database-validation/overview) * [Outcome Codes](/core-technology/database-validation/database-validation-outcome-codes) # India PAN (Permanent Account Number) (ITD) Source: https://docs.didit.me/api-reference/database-validation/india/pan-permanent-account-number POST /v3/database-validation/ Verifies input data against the database of the Income Tax Department of India. Authoritative real-time identity lookup for India. Real-time lookup, pay-per-call.
Verifies input data against the database of the Income Tax Department of India. Didit exposes this service through `POST /v3/database-validation/` so you can verify the submitted data against the authoritative source and receive normalized match results. ## Coverage * **Coverage:** \~ 100% * **Country:** India * **Service ID:** `ind_pan_permanent_account_number` * **Data domain:** Financial * **Category:** TaxRegistry ## Inputs | Field | Required | Example | | --------------- | -------: | ------------ | | `full_name` | Yes | `John Doe` | | `date_of_birth` | Yes | `1990-01-01` | | `pan` | Yes | `ABCDE1234F` | | `vendor_data` | No | `user-1234` | * **Required inputs:** `full_name`, `date_of_birth`, `pan` * **Optional inputs:** `vendor_data` * **Consent:** Required * **Workflow availability:** Available in workflow * **Coverage:** \~ 100% * **Price:** \$0.25 per successful query Not every document this service accepts carries the identifier it queries by. When the identifier is not extracted from the document the check is recorded as **not applicable** - no database is queried and you are not charged - which for some countries is a large share of real users. To cover them, also collect the identifier from a Questionnaire answer, a Document AI extraction field, or a value you send when you create the session, and map it on the Database Validation step. ## Body parameters ISO 3166-1 alpha-3 country code for this database service. Example: `IND` Array containing this service ID. Pinning the service keeps the request scoped to this exact database. Example: `ind_pan_permanent_account_number` Explicit end-user consent for this service. Example: `true` Full legal name to validate. Example: `John Doe` Date of birth in `YYYY-MM-DD` format. Example: `1990-01-01` Permanent Account Number. Example: `ABCDE1234F` Your stable user reference for this person, such as your internal user ID. Didit uses it to link standalone checks to the same end user and reduce duplicate-detection noise. Example: `user-1234` ## Input rules & validation notes * `pan` must use uppercase letters. * `pan` must match `[A-Z]{5}\d{4}[A-Z]`. ## How to call it ```bash cURL theme={null} curl -X POST "https://verification.didit.me/v3/database-validation/" \ -H "x-api-key: YOUR_API_KEY" \ -F "issuing_state=IND" \ -F "services=ind_pan_permanent_account_number" \ -F "vendor_data=user-1234" \ -F "consent=true" \ -F "full_name=John Doe" \ -F "date_of_birth=1990-01-01" \ -F "pan=ABCDE1234F" ``` Every successful call returns HTTP `200`. The **`outcome_code`** field tells you what actually happened — distinguishing, for example, a real biometric mismatch (`BIOMETRIC_NO_MATCH`) from a selfie that could not be read (`BIOMETRIC_IMAGE_UNUSABLE`). The `status` shown is the default feature status; your configured [Partial Match / No Match actions](/core-technology/database-validation/database-validation-warnings) can override it. **`MATCH`** — The registry confirmed the identity and every checked field matched. ```json 200 OK — MATCH theme={null} { "request_id": "req_01H…", "status": "Approved", "issuing_state": "IND", "match_type": "full_match", "validations": [ { "outcome_code": "MATCH", "service_id": "ind_pan_permanent_account_number", "service_name": "India PAN (Permanent Account Number) (ITD)", "source_data": { "date_of_birth": "1990-01-01", "identification_number": "SAMPLE-ID-12345", "verifications": { "date_of_birth": true, "full_name": true, "identification_number": true } }, "validation": { "date_of_birth": "full_match", "full_name": "full_match", "identification_number": "full_match" } } ] } ``` **`PARTIAL_MATCH`** — The identification number was found but one or more personal fields (usually name or date of birth) did not fully match. ```json 200 OK — PARTIAL_MATCH theme={null} { "request_id": "req_01H…", "status": "In Review", "issuing_state": "IND", "match_type": "partial_match", "validations": [ { "outcome_code": "PARTIAL_MATCH", "service_id": "ind_pan_permanent_account_number", "service_name": "India PAN (Permanent Account Number) (ITD)", "source_data": { "date_of_birth": "1990-01-01", "identification_number": "SAMPLE-ID-12345", "verifications": { "date_of_birth": true, "full_name": false, "identification_number": true } }, "validation": { "date_of_birth": "full_match", "full_name": "no_match", "identification_number": "full_match" } } ] } ``` **`NO_MATCH`** — The registry returned no match for the submitted data. ```json 200 OK — NO_MATCH theme={null} { "request_id": "req_01H…", "status": "Declined", "issuing_state": "IND", "match_type": "no_match", "validations": [ { "outcome_code": "NO_MATCH", "service_id": "ind_pan_permanent_account_number", "service_name": "India PAN (Permanent Account Number) (ITD)", "source_data": { "date_of_birth": "NO_MATCH", "full_name": "NO_MATCH", "identification_number": "NO_MATCH" }, "validation": { "date_of_birth": "no_match", "full_name": "no_match", "identification_number": "no_match" } } ] } ``` ## Returned data The exact fields surfaced in `source_data` depend on what the registry returns. The generated example for `ind_pan_permanent_account_number` currently documents this normalized shape: * `date_of_birth` * `identification_number` ## Pricing & SLAs India PAN (Permanent Account Number) (ITD) queries are billed only when Didit receives a conclusive result from the validation source. * **Per-call price:** \$0.25 USD. * **Billing:** per successful query. You are not charged when the registry is unreachable, when required fields are missing, or when the request is rejected before reaching the source. * **Latency:** typical p95 \< 2 s. * **Availability:** 99.9% per quarter on Didit's side; downstream source availability varies by country and dataset. ## Continue reading * [India Database Validation overview](/api-reference/database-validation/india) * [Database Validation overview](/core-technology/database-validation/overview) * [Outcome Codes](/core-technology/database-validation/database-validation-outcome-codes) # Indonesia Residential Identity Card Source: https://docs.didit.me/api-reference/database-validation/indonesia/residential-identity-card POST /v3/database-validation/ Verifies input data against a Government agency. Authoritative real-time identity lookup for Indonesia. Real-time lookup, pay-per-call.
Verifies input data against a Government agency. Didit exposes this service through `POST /v3/database-validation/` so you can verify the submitted data against the authoritative source and receive normalized match results. ## Coverage * **Coverage:** \~ 90% * **Country:** Indonesia * **Service ID:** `idn_residential_identity_card` * **Data domain:** Address * **Category:** Residential ## Inputs | Field | Required | Example | | --------------------- | -------: | ------------------- | | `full_name` | Yes | `John Doe` | | `date_of_birth` | Yes | `1990-01-01` | | `national_id` | Yes | `1111111111111111` | | `address.street_1` | Yes | `123 Sample Street` | | `address.postal_code` | Yes | `10001` | | `address.street_2` | No | `Unit 4` | | `address.city` | No | `Sample City` | | `address.region` | No | `Sample State` | | `gender` | No | `M` | | `vendor_data` | No | `user-1234` | * **Required inputs:** `full_name`, `date_of_birth`, `national_id`, `address.street_1`, `address.postal_code` * **Optional inputs:** `address.street_2`, `address.city`, `address.region`, `gender`, `vendor_data` * **Consent:** Required * **Workflow availability:** Available in workflow * **Coverage:** \~ 90% * **Price:** \$0.35 per successful query Not every document this service accepts carries the identifier it queries by. When the identifier is not extracted from the document the check is recorded as **not applicable** - no database is queried and you are not charged - which for some countries is a large share of real users. To cover them, also collect the identifier from a Questionnaire answer, a Document AI extraction field, or a value you send when you create the session, and map it on the Database Validation step. ## Body parameters ISO 3166-1 alpha-3 country code for this database service. Example: `IDN` Array containing this service ID. Pinning the service keeps the request scoped to this exact database. Example: `idn_residential_identity_card` Explicit end-user consent for this service. Example: `true` Full legal name to validate. Example: `John Doe` Date of birth in `YYYY-MM-DD` format. Example: `1990-01-01` National identity number for this service. Example: `1111111111111111` Structured residential address object. Use `street_1`, `street_2`, `city`, `region`, `postal_code`, and `country`. A complete legacy address string is still accepted but not recommended. Example: `{"street_1":"123 Sample Street","street_2":"Unit 4","city":"Sample City","region":"Sample State","postal_code":"10001","country":"US"}` Gender value, when required by the database. Allowed values: `M` (male), `F` (female), `X` (other or unknown). Example: `M` Your stable user reference for this person, such as your internal user ID. Didit uses it to link standalone checks to the same end user and reduce duplicate-detection noise. Example: `user-1234` ## Input rules & validation notes * `national_id` must contain digits only; remove spaces, hyphens, and punctuation before sending the request. * `national_id` must be exactly 16 characters long. * For address services, send structured address fields instead of a single `address` string when possible. * `address.street_1` is the street address, including street number and street type. * `address.street_2` is apartment, unit, building, floor, or extra address line. Send it only when you have it. * `address.city` is city, suburb, district, locality, or neighborhood. * `address.region` is state, province, region, or town. * `address.postal_code` is postcode or postal code. * Address-based database services require at least street address and postal code; requests rejected before source lookup are not charged. ## How to call it ```bash cURL theme={null} curl -X POST "https://verification.didit.me/v3/database-validation/" \ -H "x-api-key: YOUR_API_KEY" \ -F "issuing_state=IDN" \ -F "services=idn_residential_identity_card" \ -F "vendor_data=user-1234" \ -F "consent=true" \ -F "full_name=John Doe" \ -F "date_of_birth=1990-01-01" \ -F "national_id=1111111111111111" \ -F 'address={"street_1":"123 Sample Street","street_2":"Unit 4","city":"Sample City","region":"Sample State","postal_code":"10001","country":"US"}' ``` Every successful call returns HTTP `200`. The **`outcome_code`** field tells you what actually happened — distinguishing, for example, a real biometric mismatch (`BIOMETRIC_NO_MATCH`) from a selfie that could not be read (`BIOMETRIC_IMAGE_UNUSABLE`). The `status` shown is the default feature status; your configured [Partial Match / No Match actions](/core-technology/database-validation/database-validation-warnings) can override it. **`MATCH`** — The registry confirmed the identity and every checked field matched. ```json 200 OK — MATCH theme={null} { "request_id": "req_01H…", "status": "Approved", "issuing_state": "IDN", "match_type": "full_match", "validations": [ { "outcome_code": "MATCH", "service_id": "idn_residential_identity_card", "service_name": "Indonesia Residential Identity Card", "source_data": { "address_match_score": "1.000", "date_of_birth": "1990-01-01", "identification_number": "SAMPLE-ID-12345", "verifications": { "address": true, "date_of_birth": true, "full_name": true, "identification_number": true } }, "validation": { "address": "full_match", "date_of_birth": "full_match", "full_name": "full_match", "identification_number": "full_match" } } ] } ``` **`PARTIAL_MATCH`** — The identification number was found but one or more personal fields (usually name or date of birth) did not fully match. ```json 200 OK — PARTIAL_MATCH theme={null} { "request_id": "req_01H…", "status": "In Review", "issuing_state": "IDN", "match_type": "partial_match", "validations": [ { "outcome_code": "PARTIAL_MATCH", "service_id": "idn_residential_identity_card", "service_name": "Indonesia Residential Identity Card", "source_data": { "address_match_score": "1.000", "date_of_birth": "1990-01-01", "identification_number": "SAMPLE-ID-12345", "verifications": { "address": true, "date_of_birth": true, "full_name": false, "identification_number": true } }, "validation": { "address": "full_match", "date_of_birth": "full_match", "full_name": "no_match", "identification_number": "full_match" } } ] } ``` **`NO_MATCH`** — The registry returned no match for the submitted data. ```json 200 OK — NO_MATCH theme={null} { "request_id": "req_01H…", "status": "Declined", "issuing_state": "IDN", "match_type": "no_match", "validations": [ { "outcome_code": "NO_MATCH", "service_id": "idn_residential_identity_card", "service_name": "Indonesia Residential Identity Card", "source_data": { "address": "NO_MATCH", "date_of_birth": "NO_MATCH", "full_name": "NO_MATCH", "identification_number": "NO_MATCH" }, "validation": { "address": "no_match", "date_of_birth": "no_match", "full_name": "no_match", "identification_number": "no_match" } } ] } ``` ## Returned data The exact fields surfaced in `source_data` depend on what the registry returns. The generated example for `idn_residential_identity_card` currently documents this normalized shape: * `address_match_score` * `date_of_birth` * `identification_number` ## Pricing & SLAs Indonesia Residential Identity Card queries are billed only when Didit receives a conclusive result from the validation source. * **Per-call price:** \$0.35 USD. * **Billing:** per successful query. You are not charged when the registry is unreachable, when required fields are missing, or when the request is rejected before reaching the source. * **Latency:** typical p95 \< 2 s. * **Availability:** 99.9% per quarter on Didit's side; downstream source availability varies by country and dataset. ## Continue reading * [Indonesia Database Validation overview](/api-reference/database-validation/indonesia) * [Database Validation overview](/core-technology/database-validation/overview) * [Outcome Codes](/core-technology/database-validation/database-validation-outcome-codes) # Italy Credit Bureau Source: https://docs.didit.me/api-reference/database-validation/italy/credit-bureau POST /v3/database-validation/ Verifies input data against Credit Header data obtained from a Credit Bureau in Italy. Authoritative real-time identity lookup for Italy. Real-time lookup, pay-per-call.
Verifies input data against Credit Header data obtained from a Credit Bureau in Italy. Didit exposes this service through `POST /v3/database-validation/` so you can verify the submitted data against the authoritative source and receive normalized match results. ## Coverage * **Coverage:** \~ 80% * **Country:** Italy * **Service ID:** `ita_credit_bureau` * **Data domain:** Financial * **Category:** CreditBureau ## Inputs | Field | Required | Example | | --------------------- | -------: | ------------------- | | `first_name` | Yes | `John` | | `last_name` | Yes | `Doe` | | `address.street_1` | Yes | `123 Sample Street` | | `address.postal_code` | Yes | `10001` | | `tax_number` | Yes | `SAMPLE-TAX-12345` | | `date_of_birth` | No | `1990-01-01` | | `address.street_2` | No | `Unit 4` | | `address.city` | No | `Sample City` | | `address.region` | No | `Sample State` | | `vendor_data` | No | `user-1234` | * **Required inputs:** `first_name`, `last_name`, `address.street_1`, `address.postal_code`, `tax_number` * **Optional inputs:** `date_of_birth`, `address.street_2`, `address.city`, `address.region`, `vendor_data` * **Consent:** Not required * **Workflow availability:** Available in workflow * **Coverage:** \~ 80% * **Price:** \$1.95 per successful query Not every document this service accepts carries the identifier it queries by. When the identifier is not extracted from the document the check is recorded as **not applicable** - no database is queried and you are not charged - which for some countries is a large share of real users. To cover them, also collect the identifier from a Questionnaire answer, a Document AI extraction field, or a value you send when you create the session, and map it on the Database Validation step. ## Body parameters ISO 3166-1 alpha-3 country code for this database service. Example: `ITA` Array containing this service ID. Pinning the service keeps the request scoped to this exact database. Example: `ita_credit_bureau` Given name to validate. Example: `John` Family name to validate. Example: `Doe` Structured residential address object. Use `street_1`, `street_2`, `city`, `region`, `postal_code`, and `country`. A complete legacy address string is still accepted but not recommended. Example: `{"street_1":"123 Sample Street","street_2":"Unit 4","city":"Sample City","region":"Sample State","postal_code":"10001","country":"US"}` Tax or fiscal identification number. Example: `SAMPLE-TAX-12345` Date of birth in `YYYY-MM-DD` format. Example: `1990-01-01` Your stable user reference for this person, such as your internal user ID. Didit uses it to link standalone checks to the same end user and reduce duplicate-detection noise. Example: `user-1234` ## Input rules & validation notes * `tax_number` must be exactly 16 characters long. * For address services, send structured address fields instead of a single `address` string when possible. * `address.street_1` is the street address, including street number and street type. * `address.street_2` is apartment, unit, building, floor, or extra address line. Send it only when you have it. * `address.city` is city, suburb, district, locality, or neighborhood. * `address.region` is state, province, region, or town. * `address.postal_code` is postcode or postal code. * Address-based database services require at least street address and postal code; requests rejected before source lookup are not charged. ## How to call it ```bash cURL theme={null} curl -X POST "https://verification.didit.me/v3/database-validation/" \ -H "x-api-key: YOUR_API_KEY" \ -F "issuing_state=ITA" \ -F "services=ita_credit_bureau" \ -F "vendor_data=user-1234" \ -F "first_name=John" \ -F "last_name=Doe" \ -F 'address={"street_1":"123 Sample Street","street_2":"Unit 4","city":"Sample City","region":"Sample State","postal_code":"10001","country":"US"}' \ -F "tax_number=SAMPLE-TAX-12345" ``` Every successful call returns HTTP `200`. The **`outcome_code`** field tells you what actually happened — distinguishing, for example, a real biometric mismatch (`BIOMETRIC_NO_MATCH`) from a selfie that could not be read (`BIOMETRIC_IMAGE_UNUSABLE`). The `status` shown is the default feature status; your configured [Partial Match / No Match actions](/core-technology/database-validation/database-validation-warnings) can override it. **`MATCH`** — The registry confirmed the identity and every checked field matched. ```json 200 OK — MATCH theme={null} { "request_id": "req_01H…", "status": "Approved", "issuing_state": "ITA", "match_type": "full_match", "validations": [ { "outcome_code": "MATCH", "service_id": "ita_credit_bureau", "service_name": "Italy Credit Bureau", "source_data": { "address": "123 Sample Street", "date_of_birth": "1990-01-01", "first_name": "John", "identification_number": "SAMPLE-ID-12345", "last_name": "Doe" }, "validation": { "address": "full_match", "full_name": "full_match", "identification_number": "full_match" } } ] } ``` **`PARTIAL_MATCH`** — The identification number was found but one or more personal fields (usually name or date of birth) did not fully match. ```json 200 OK — PARTIAL_MATCH theme={null} { "request_id": "req_01H…", "status": "In Review", "issuing_state": "ITA", "match_type": "partial_match", "validations": [ { "outcome_code": "PARTIAL_MATCH", "service_id": "ita_credit_bureau", "service_name": "Italy Credit Bureau", "source_data": { "address": "123 Sample Street", "date_of_birth": "1990-01-01", "first_name": "John", "identification_number": "SAMPLE-ID-12345", "last_name": "Doe" }, "validation": { "address": "full_match", "full_name": "no_match", "identification_number": "full_match" } } ] } ``` **`NO_MATCH`** — The registry returned no match for the submitted data. ```json 200 OK — NO_MATCH theme={null} { "request_id": "req_01H…", "status": "Declined", "issuing_state": "ITA", "match_type": "no_match", "validations": [ { "outcome_code": "NO_MATCH", "service_id": "ita_credit_bureau", "service_name": "Italy Credit Bureau", "source_data": { "address": "NO_MATCH", "full_name": "NO_MATCH", "identification_number": "NO_MATCH" }, "validation": { "address": "no_match", "full_name": "no_match", "identification_number": "no_match" } } ] } ``` ## Returned data The exact fields surfaced in `source_data` depend on what the registry returns. The generated example for `ita_credit_bureau` currently documents this normalized shape: * `address` * `date_of_birth` * `first_name` * `identification_number` * `last_name` ## Pricing & SLAs Italy Credit Bureau queries are billed only when Didit receives a conclusive result from the validation source. * **Per-call price:** \$1.95 USD. * **Billing:** per successful query. You are not charged when the registry is unreachable, when required fields are missing, or when the request is rejected before reaching the source. * **Latency:** typical p95 \< 2 s. * **Availability:** 99.9% per quarter on Didit's side; downstream source availability varies by country and dataset. ## Continue reading * [Italy Database Validation overview](/api-reference/database-validation/italy) * [Database Validation overview](/core-technology/database-validation/overview) * [Outcome Codes](/core-technology/database-validation/database-validation-outcome-codes) # Italy Residential Source: https://docs.didit.me/api-reference/database-validation/italy/residential POST /v3/database-validation/ Input is verified against a source comprising multiple datasets from consumer, telephone and postal records. Authoritative real-time identity lookup for Italy. Real-time lookup, pay-per-call.
Input is verified against a source comprising multiple datasets from consumer, telephone and postal records. Didit exposes this service through `POST /v3/database-validation/` so you can verify the submitted data against the authoritative source and receive normalized match results. ## Coverage * **Coverage:** > 75% * **Country:** Italy * **Service ID:** `ita_residential` * **Data domain:** Address * **Category:** Residential ## Inputs | Field | Required | Example | | --------------------- | -------: | ------------------- | | `first_name` | Yes | `John` | | `last_name` | Yes | `Doe` | | `date_of_birth` | Yes | `1990-01-01` | | `address.street_1` | Yes | `123 Sample Street` | | `address.postal_code` | Yes | `10001` | | `address.street_2` | No | `Unit 4` | | `address.city` | No | `Sample City` | | `address.region` | No | `Sample State` | | `vendor_data` | No | `user-1234` | * **Required inputs:** `first_name`, `last_name`, `date_of_birth`, `address.street_1`, `address.postal_code` * **Optional inputs:** `address.street_2`, `address.city`, `address.region`, `vendor_data` * **Consent:** Not required * **Workflow availability:** Available in workflow * **Coverage:** > 75% * **Price:** \$0.45 per successful query ## Body parameters ISO 3166-1 alpha-3 country code for this database service. Example: `ITA` Array containing this service ID. Pinning the service keeps the request scoped to this exact database. Example: `ita_residential` Given name to validate. Example: `John` Family name to validate. Example: `Doe` Date of birth in `YYYY-MM-DD` format. Example: `1990-01-01` Structured residential address object. Use `street_1`, `street_2`, `city`, `region`, `postal_code`, and `country`. A complete legacy address string is still accepted but not recommended. Example: `{"street_1":"123 Sample Street","street_2":"Unit 4","city":"Sample City","region":"Sample State","postal_code":"10001","country":"US"}` Your stable user reference for this person, such as your internal user ID. Didit uses it to link standalone checks to the same end user and reduce duplicate-detection noise. Example: `user-1234` ## Input rules & validation notes * For address services, send structured address fields instead of a single `address` string when possible. * `address.street_1` is the street address, including street number and street type. * `address.street_2` is apartment, unit, building, floor, or extra address line. Send it only when you have it. * `address.city` is city, suburb, district, locality, or neighborhood. * `address.region` is state, province, region, or town. * `address.postal_code` is postcode or postal code. * Address-based database services require at least street address and postal code; requests rejected before source lookup are not charged. ## How to call it ```bash cURL theme={null} curl -X POST "https://verification.didit.me/v3/database-validation/" \ -H "x-api-key: YOUR_API_KEY" \ -F "issuing_state=ITA" \ -F "services=ita_residential" \ -F "vendor_data=user-1234" \ -F "first_name=John" \ -F "last_name=Doe" \ -F "date_of_birth=1990-01-01" \ -F 'address={"street_1":"123 Sample Street","street_2":"Unit 4","city":"Sample City","region":"Sample State","postal_code":"10001","country":"US"}' ``` Every successful call returns HTTP `200`. The **`outcome_code`** field tells you what actually happened — distinguishing, for example, a real biometric mismatch (`BIOMETRIC_NO_MATCH`) from a selfie that could not be read (`BIOMETRIC_IMAGE_UNUSABLE`). The `status` shown is the default feature status; your configured [Partial Match / No Match actions](/core-technology/database-validation/database-validation-warnings) can override it. **`MATCH`** — The registry confirmed the identity and every checked field matched. ```json 200 OK — MATCH theme={null} { "request_id": "req_01H…", "status": "Approved", "issuing_state": "ITA", "match_type": "full_match", "validations": [ { "outcome_code": "MATCH", "service_id": "ita_residential", "service_name": "Italy Residential", "source_data": { "address": "123 Sample Street", "address_match_score": "1.000", "city": "Sample City", "date_of_birth": "1990-01-01", "first_name": "John", "full_name": "John Doe", "last_name": "Doe", "name_match_score": "1.000", "postal_code": "10001", "street": "sample_value", "verifications": { "address": true, "date_of_birth": true, "full_name": true } }, "validation": { "address": "full_match", "date_of_birth": "full_match", "full_name": "full_match" } } ] } ``` **`PARTIAL_MATCH`** — The identification number was found but one or more personal fields (usually name or date of birth) did not fully match. ```json 200 OK — PARTIAL_MATCH theme={null} { "request_id": "req_01H…", "status": "In Review", "issuing_state": "ITA", "match_type": "partial_match", "validations": [ { "outcome_code": "PARTIAL_MATCH", "service_id": "ita_residential", "service_name": "Italy Residential", "source_data": { "address": "123 Sample Street", "address_match_score": "1.000", "city": "Sample City", "date_of_birth": "1990-01-01", "first_name": "John", "full_name": "John Doe", "last_name": "Doe", "name_match_score": "1.000", "postal_code": "10001", "street": "sample_value", "verifications": { "address": true, "date_of_birth": true, "full_name": false } }, "validation": { "address": "full_match", "date_of_birth": "full_match", "full_name": "no_match" } } ] } ``` **`NO_MATCH`** — The registry returned no match for the submitted data. ```json 200 OK — NO_MATCH theme={null} { "request_id": "req_01H…", "status": "Declined", "issuing_state": "ITA", "match_type": "no_match", "validations": [ { "outcome_code": "NO_MATCH", "service_id": "ita_residential", "service_name": "Italy Residential", "source_data": { "address": "NO_MATCH", "date_of_birth": "NO_MATCH", "full_name": "NO_MATCH" }, "validation": { "address": "no_match", "date_of_birth": "no_match", "full_name": "no_match" } } ] } ``` ## Returned data The exact fields surfaced in `source_data` depend on what the registry returns. The generated example for `ita_residential` currently documents this normalized shape: * `address` * `address_match_score` * `city` * `date_of_birth` * `first_name` * `full_name` * `last_name` * `name_match_score` * `postal_code` * `street` ## Pricing & SLAs Italy Residential queries are billed only when Didit receives a conclusive result from the validation source. * **Per-call price:** \$0.45 USD. * **Billing:** per successful query. You are not charged when the registry is unreachable, when required fields are missing, or when the request is rejected before reaching the source. * **Latency:** typical p95 \< 2 s. * **Availability:** 99.9% per quarter on Didit's side; downstream source availability varies by country and dataset. ## Continue reading * [Italy Database Validation overview](/api-reference/database-validation/italy) * [Database Validation overview](/core-technology/database-validation/overview) * [Outcome Codes](/core-technology/database-validation/database-validation-outcome-codes) # Kenya National ID Source: https://docs.didit.me/api-reference/database-validation/kenya/national-id POST /v3/database-validation/ Verifies data against the National Registration Bureau. Authoritative real-time identity lookup for Kenya. Real-time lookup, pay-per-call.
Verifies data against the National Registration Bureau. Didit exposes this service through `POST /v3/database-validation/` so you can verify the submitted data against the authoritative source and receive normalized match results. ## Coverage * **Coverage:** \~ 90% * **Country:** Kenya * **Service ID:** `ken_national_id` * **Data domain:** Identity * **Category:** NationalIDRegistry ## Inputs | Field | Required | Example | | --------------- | -------: | ------------------ | | `first_name` | Yes | `John` | | `last_name` | Yes | `Doe` | | `date_of_birth` | Yes | `1990-01-01` | | `national_id` | Yes | `SAMPLE-NID-12345` | | `vendor_data` | No | `user-1234` | * **Required inputs:** `first_name`, `last_name`, `date_of_birth`, `national_id` * **Optional inputs:** `vendor_data` * **Consent:** Not required * **Workflow availability:** Available in workflow * **Coverage:** \~ 90% * **Price:** \$3.15 per successful query Not every document this service accepts carries the identifier it queries by. When the identifier is not extracted from the document the check is recorded as **not applicable** - no database is queried and you are not charged - which for some countries is a large share of real users. To cover them, also collect the identifier from a Questionnaire answer, a Document AI extraction field, or a value you send when you create the session, and map it on the Database Validation step. ## Body parameters ISO 3166-1 alpha-3 country code for this database service. Example: `KEN` Array containing this service ID. Pinning the service keeps the request scoped to this exact database. Example: `ken_national_id` Given name to validate. Example: `John` Family name to validate. Example: `Doe` Date of birth in `YYYY-MM-DD` format. Example: `1990-01-01` National identity number for this service. Example: `SAMPLE-NID-12345` Your stable user reference for this person, such as your internal user ID. Didit uses it to link standalone checks to the same end user and reduce duplicate-detection noise. Example: `user-1234` ## Input rules & validation notes * `national_id` must match `\d{8,9}`. ## How to call it ```bash cURL theme={null} curl -X POST "https://verification.didit.me/v3/database-validation/" \ -H "x-api-key: YOUR_API_KEY" \ -F "issuing_state=KEN" \ -F "services=ken_national_id" \ -F "vendor_data=user-1234" \ -F "first_name=John" \ -F "last_name=Doe" \ -F "date_of_birth=1990-01-01" \ -F "national_id=SAMPLE-NID-12345" ``` Every successful call returns HTTP `200`. The **`outcome_code`** field tells you what actually happened — distinguishing, for example, a real biometric mismatch (`BIOMETRIC_NO_MATCH`) from a selfie that could not be read (`BIOMETRIC_IMAGE_UNUSABLE`). The `status` shown is the default feature status; your configured [Partial Match / No Match actions](/core-technology/database-validation/database-validation-warnings) can override it. **`MATCH`** — The registry confirmed the identity and every checked field matched. ```json 200 OK — MATCH theme={null} { "request_id": "req_01H…", "status": "Approved", "issuing_state": "KEN", "match_type": "full_match", "validations": [ { "outcome_code": "MATCH", "service_id": "ken_national_id", "service_name": "Kenya National ID", "source_data": { "date_of_birth": "1990-01-01", "first_name": "John", "full_name": "John Doe", "identification_number": "SAMPLE-ID-12345", "last_name": "Doe", "name_match_score": "1.000", "verifications": { "date_of_birth": true, "full_name": true, "identification_number": true } }, "validation": { "date_of_birth": "full_match", "full_name": "full_match", "identification_number": "full_match" } } ] } ``` **`PARTIAL_MATCH`** — The identification number was found but one or more personal fields (usually name or date of birth) did not fully match. ```json 200 OK — PARTIAL_MATCH theme={null} { "request_id": "req_01H…", "status": "In Review", "issuing_state": "KEN", "match_type": "partial_match", "validations": [ { "outcome_code": "PARTIAL_MATCH", "service_id": "ken_national_id", "service_name": "Kenya National ID", "source_data": { "date_of_birth": "1990-01-01", "first_name": "John", "full_name": "John Doe", "identification_number": "SAMPLE-ID-12345", "last_name": "Doe", "name_match_score": "1.000", "verifications": { "date_of_birth": true, "full_name": false, "identification_number": true } }, "validation": { "date_of_birth": "full_match", "full_name": "no_match", "identification_number": "full_match" } } ] } ``` **`NO_MATCH`** — The registry returned no match for the submitted data. ```json 200 OK — NO_MATCH theme={null} { "request_id": "req_01H…", "status": "Declined", "issuing_state": "KEN", "match_type": "no_match", "validations": [ { "outcome_code": "NO_MATCH", "service_id": "ken_national_id", "service_name": "Kenya National ID", "source_data": { "date_of_birth": "NO_MATCH", "full_name": "NO_MATCH", "identification_number": "NO_MATCH" }, "validation": { "date_of_birth": "no_match", "full_name": "no_match", "identification_number": "no_match" } } ] } ``` ## Returned data The exact fields surfaced in `source_data` depend on what the registry returns. The generated example for `ken_national_id` currently documents this normalized shape: * `date_of_birth` * `first_name` * `full_name` * `identification_number` * `last_name` * `name_match_score` ## Pricing & SLAs Kenya National ID queries are billed only when Didit receives a conclusive result from the validation source. * **Per-call price:** \$3.15 USD. * **Billing:** per successful query. You are not charged when the registry is unreachable, when required fields are missing, or when the request is rejected before reaching the source. * **Latency:** typical p95 \< 2 s. * **Availability:** 99.9% per quarter on Didit's side; downstream source availability varies by country and dataset. ## Continue reading * [Kenya Database Validation overview](/api-reference/database-validation/kenya) * [Database Validation overview](/core-technology/database-validation/overview) * [Outcome Codes](/core-technology/database-validation/database-validation-outcome-codes) # Malaysia National ID Source: https://docs.didit.me/api-reference/database-validation/malaysia/national-id POST /v3/database-validation/ Verifies input data against a Government agency database consisting of Malaysian citizens data. Authoritative real-time identity lookup for Malaysia. Real-time lookup, pay-per-call.
Verifies input data against a Government agency database consisting of Malaysian citizens data. Didit exposes this service through `POST /v3/database-validation/` so you can verify the submitted data against the authoritative source and receive normalized match results. ## Coverage * **Coverage:** > 75% * **Country:** Malaysia * **Service ID:** `mys_national_id` * **Data domain:** Identity * **Category:** NationalIDRegistry ## Inputs | Field | Required | Example | | --------------------- | -------: | ------------------- | | `full_name` | Yes | `John Doe` | | `date_of_birth` | Yes | `1990-01-01` | | `national_id` | Yes | `111111111111` | | `address.street_1` | No | `123 Sample Street` | | `address.street_2` | No | `Unit 4` | | `address.city` | No | `Sample City` | | `address.region` | No | `Sample State` | | `address.postal_code` | No | `10001` | | `phone` | No | `+15550101000` | | `vendor_data` | No | `user-1234` | * **Required inputs:** `full_name`, `date_of_birth`, `national_id` * **Optional inputs:** `address.street_1`, `address.street_2`, `address.city`, `address.region`, `address.postal_code`, `phone`, `vendor_data` * **Consent:** Required * **Workflow availability:** Available in workflow * **Coverage:** > 75% * **Price:** \$0.35 per successful query Not every document this service accepts carries the identifier it queries by. When the identifier is not extracted from the document the check is recorded as **not applicable** - no database is queried and you are not charged - which for some countries is a large share of real users. To cover them, also collect the identifier from a Questionnaire answer, a Document AI extraction field, or a value you send when you create the session, and map it on the Database Validation step. ## Body parameters ISO 3166-1 alpha-3 country code for this database service. Example: `MYS` Array containing this service ID. Pinning the service keeps the request scoped to this exact database. Example: `mys_national_id` Explicit end-user consent for this service. Example: `true` Full legal name to validate. Example: `John Doe` Date of birth in `YYYY-MM-DD` format. Example: `1990-01-01` National identity number for this service. Example: `111111111111` Structured residential address object. Use `street_1`, `street_2`, `city`, `region`, `postal_code`, and `country`. A complete legacy address string is still accepted but not recommended. Example: `{"street_1":"123 Sample Street","street_2":"Unit 4","city":"Sample City","region":"Sample State","postal_code":"10001","country":"US"}` Phone number in international format. Example: `+15550101000` Your stable user reference for this person, such as your internal user ID. Didit uses it to link standalone checks to the same end user and reduce duplicate-detection noise. Example: `user-1234` ## Input rules & validation notes * `address` is optional for this service. You can send one complete `address` string and Didit will split it into structured address elements when possible, or you can send the structured fields explicitly. * `national_id` must contain digits only; remove spaces, hyphens, and punctuation before sending the request. * `national_id` must be exactly 12 characters long. * For address services, send structured address fields instead of a single `address` string when possible. * `address.street_1` is the street address, including street number and street type. * `address.street_2` is apartment, unit, building, floor, or extra address line. Send it only when you have it. * `address.city` is city, suburb, district, locality, or neighborhood. * `address.region` is state, province, region, or town. * `address.postal_code` is postcode or postal code. * Address-based database services require at least street address and postal code; requests rejected before source lookup are not charged. ## How to call it ```bash cURL theme={null} curl -X POST "https://verification.didit.me/v3/database-validation/" \ -H "x-api-key: YOUR_API_KEY" \ -F "issuing_state=MYS" \ -F "services=mys_national_id" \ -F "vendor_data=user-1234" \ -F "consent=true" \ -F "full_name=John Doe" \ -F "date_of_birth=1990-01-01" \ -F "national_id=111111111111" ``` Every successful call returns HTTP `200`. The **`outcome_code`** field tells you what actually happened — distinguishing, for example, a real biometric mismatch (`BIOMETRIC_NO_MATCH`) from a selfie that could not be read (`BIOMETRIC_IMAGE_UNUSABLE`). The `status` shown is the default feature status; your configured [Partial Match / No Match actions](/core-technology/database-validation/database-validation-warnings) can override it. **`MATCH`** — The registry confirmed the identity and every checked field matched. ```json 200 OK — MATCH theme={null} { "request_id": "req_01H…", "status": "Approved", "issuing_state": "MYS", "match_type": "full_match", "validations": [ { "outcome_code": "MATCH", "service_id": "mys_national_id", "service_name": "Malaysia National ID", "source_data": { "address": "123 Sample Street", "address_match_score": "1.000", "city": "Sample City", "date_of_birth": "1990-01-01", "identification_number": "SAMPLE-ID-12345", "postal_code": "10001", "state": "Sample State", "street": "sample_value" }, "validation": { "date_of_birth": "full_match", "full_name": "full_match", "identification_number": "full_match" } } ] } ``` **`PARTIAL_MATCH`** — The identification number was found but one or more personal fields (usually name or date of birth) did not fully match. ```json 200 OK — PARTIAL_MATCH theme={null} { "request_id": "req_01H…", "status": "In Review", "issuing_state": "MYS", "match_type": "partial_match", "validations": [ { "outcome_code": "PARTIAL_MATCH", "service_id": "mys_national_id", "service_name": "Malaysia National ID", "source_data": { "address": "123 Sample Street", "address_match_score": "1.000", "city": "Sample City", "date_of_birth": "1990-01-01", "identification_number": "SAMPLE-ID-12345", "postal_code": "10001", "state": "Sample State", "street": "sample_value" }, "validation": { "date_of_birth": "full_match", "full_name": "no_match", "identification_number": "full_match" } } ] } ``` **`NO_MATCH`** — The registry returned no match for the submitted data. ```json 200 OK — NO_MATCH theme={null} { "request_id": "req_01H…", "status": "Declined", "issuing_state": "MYS", "match_type": "no_match", "validations": [ { "outcome_code": "NO_MATCH", "service_id": "mys_national_id", "service_name": "Malaysia National ID", "source_data": { "date_of_birth": "NO_MATCH", "full_name": "NO_MATCH", "identification_number": "NO_MATCH" }, "validation": { "date_of_birth": "no_match", "full_name": "no_match", "identification_number": "no_match" } } ] } ``` ## Returned data The exact fields surfaced in `source_data` depend on what the registry returns. The generated example for `mys_national_id` currently documents this normalized shape: * `address` * `address_match_score` * `city` * `date_of_birth` * `identification_number` * `postal_code` * `state` * `street` ## Pricing & SLAs Malaysia National ID queries are billed only when Didit receives a conclusive result from the validation source. * **Per-call price:** \$0.35 USD. * **Billing:** per successful query. You are not charged when the registry is unreachable, when required fields are missing, or when the request is rejected before reaching the source. * **Latency:** typical p95 \< 2 s. * **Availability:** 99.9% per quarter on Didit's side; downstream source availability varies by country and dataset. ## Continue reading * [Malaysia Database Validation overview](/api-reference/database-validation/malaysia) * [Database Validation overview](/core-technology/database-validation/overview) * [Outcome Codes](/core-technology/database-validation/database-validation-outcome-codes) # Mexico - CURP verification Source: https://docs.didit.me/api-reference/database-validation/mexico/curp POST /v3/database-validation/ Verifies Mexican CURP against the RENAPO national identifier registry. Authoritative real-time identity lookup for Mexico. Real-time lookup, pay-per-call.
Verifies Mexican CURP against the RENAPO national identifier registry. Didit exposes this service through `POST /v3/database-validation/` so you can verify the submitted data against the authoritative source and receive normalized match results. ## Coverage * **Coverage:** \~ 100% * **Country:** Mexico * **Service ID:** `mex_curp` * **Data domain:** Identity * **Category:** NationalIDRegistry ## Inputs | Field | Required | Example | | ----------------- | -------: | -------------------- | | `personal_number` | Yes | `ABCD900101HDFABC09` | | `first_name` | No | `John` | | `last_name` | No | `Doe` | | `vendor_data` | No | `user-1234` | * **Required inputs:** `personal_number` * **Optional inputs:** `first_name`, `last_name`, `vendor_data` * **Consent:** Not required * **Workflow availability:** Available in workflow * **Coverage:** \~ 100% * **Price:** \$0.20 per successful query ## Body parameters ISO 3166-1 alpha-3 country code for this database service. Example: `MEX` Array containing this service ID. Pinning the service keeps the request scoped to this exact database. Example: `mex_curp` Country-specific personal identity number. Example: `ABCD900101HDFABC09` Given name to validate. Example: `John` Family name to validate. Example: `Doe` Your stable user reference for this person, such as your internal user ID. Didit uses it to link standalone checks to the same end user and reduce duplicate-detection noise. Example: `user-1234` ## Input rules & validation notes * Mexican CURP (exactly 18 alphanumeric characters) * `personal_number` must be exactly 18 characters long. ## How to call it ```bash cURL theme={null} curl -X POST "https://verification.didit.me/v3/database-validation/" \ -H "x-api-key: YOUR_API_KEY" \ -F "issuing_state=MEX" \ -F "services=mex_curp" \ -F "vendor_data=user-1234" \ -F "personal_number=ABCD900101HDFABC09" ``` Every successful call returns HTTP `200`. The **`outcome_code`** field tells you what actually happened — distinguishing, for example, a real biometric mismatch (`BIOMETRIC_NO_MATCH`) from a selfie that could not be read (`BIOMETRIC_IMAGE_UNUSABLE`). The `status` shown is the default feature status; your configured [Partial Match / No Match actions](/core-technology/database-validation/database-validation-warnings) can override it. **`MATCH`** — The registry confirmed the identity and every checked field matched. ```json 200 OK — MATCH theme={null} { "request_id": "req_01H…", "status": "Approved", "issuing_state": "MEX", "match_type": "full_match", "validations": [ { "outcome_code": "MATCH", "service_id": "mex_curp", "service_name": "Mexico - CURP verification", "source_data": { "curp_status": "sample_value", "date_of_birth": "1990-01-01", "doc_probatorio": "sample_value", "first_name": "John", "full_name": "John Doe", "gender": "M", "identification_number": "SAMPLE-ID-12345", "last_name": "Doe", "nationality": "USA", "num_acta": "sample_value", "registration_municipality": "sample_value", "registration_state": "sample_value", "registration_year": "sample_value", "state_of_birth": "sample_value" }, "validation": { "identification_number": "full_match" } } ] } ``` **`NO_MATCH`** — The registry returned no match for the submitted data. ```json 200 OK — NO_MATCH theme={null} { "request_id": "req_01H…", "status": "Declined", "issuing_state": "MEX", "match_type": "no_match", "validations": [ { "outcome_code": "NO_MATCH", "service_id": "mex_curp", "service_name": "Mexico - CURP verification", "source_data": { "identification_number": "NO_MATCH" }, "validation": { "identification_number": "no_match" } } ] } ``` ## Returned data The exact fields surfaced in `source_data` depend on what the registry returns. The generated example for `mex_curp` currently documents this normalized shape: * `curp_status` * `date_of_birth` * `doc_probatorio` * `first_name` * `full_name` * `gender` * `identification_number` * `last_name` * `nationality` * `num_acta` * `registration_municipality` * `registration_state` * `registration_year` * `state_of_birth` ## Pricing & SLAs Mexico - CURP verification queries are billed only when Didit receives a conclusive result from the validation source. * **Per-call price:** \$0.20 USD. * **Billing:** per successful query. You are not charged when the registry is unreachable, when required fields are missing, or when the request is rejected before reaching the source. * **Latency:** typical p95 \< 2 s. * **Availability:** 99.9% per quarter on Didit's side; downstream source availability varies by country and dataset. ## Continue reading * [Mexico Database Validation overview](/api-reference/database-validation/mexico) * [Database Validation overview](/core-technology/database-validation/overview) * [Outcome Codes](/core-technology/database-validation/database-validation-outcome-codes) # Mexico - INE credential validity verification Source: https://docs.didit.me/api-reference/database-validation/mexico/ine-vigencia POST /v3/database-validation/ Verifies a Mexican INE / IFE voter ID credential against the INE registry (modelo, vigencia, válida-como-identificación, derecho-a-votar). Authoritative real-time identity lookup for Mexico. Real-time lookup, pay-per-call.
Verifies a Mexican INE / IFE voter ID credential against the INE registry (modelo, vigencia, válida-como-identificación, derecho-a-votar). Didit exposes this service through `POST /v3/database-validation/` so you can verify the submitted data against the authoritative source and receive normalized match results. ## Coverage * **Coverage:** — * **Country:** Mexico * **Service ID:** `mex_ine_vigencia` * **Data domain:** Identity * **Category:** NationalIDRegistry ## Inputs | Field | Required | Example | | ------------------------- | -------: | --------------- | | `cic` | No | `123456789` | | `identificador_ciudadano` | No | `123456789` | | `ocr` | No | `1234567890123` | | `voter_number` | No | `ABCDEF123456` | | `emission_number` | No | `01` | | `first_name` | No | `John` | | `last_name` | No | `Doe` | | `date_of_birth` | No | `1990-01-01` | | `vendor_data` | No | `user-1234` | * **Required inputs:** — * **Optional inputs:** `cic`, `identificador_ciudadano`, `ocr`, `voter_number`, `emission_number`, `first_name`, `last_name`, `date_of_birth`, `vendor_data` * **Consent:** Not required * **Workflow availability:** Available in workflow * **Coverage:** — * **Price:** \$0.20 per successful query ## Body parameters ISO 3166-1 alpha-3 country code for this database service. Example: `MEX` Array containing this service ID. Pinning the service keeps the request scoped to this exact database. Example: `mex_ine_vigencia` `cic` value required by this database service. Example: `123456789` `identificador_ciudadano` value required by this database service. Example: `123456789` `ocr` value required by this database service. Example: `1234567890123` `voter_number` value required by this database service. Example: `ABCDEF123456` `emission_number` value required by this database service. Example: `01` Given name to validate. Example: `John` Family name to validate. Example: `Doe` Date of birth in `YYYY-MM-DD` format. Example: `1990-01-01` Your stable user reference for this person, such as your internal user ID. Didit uses it to link standalone checks to the same end user and reduce duplicate-detection noise. Example: `user-1234` ## Input rules & validation notes * Provide at least one credential identifier: `cic`, `identificador_ciudadano`, `ocr`, or `voter_number`. If all are absent, Didit returns HTTP `400` with the accepted fields instead of calling the provider. Requests rejected before source lookup are not charged. * For a legacy credential identified by `voter_number`, include `emission_number`. * A provider rejection remains a completed HTTP `200` validation and carries the real normalized result. For example, provider code `4` is returned as `outcome_code: "INVALID_DOCUMENT_FORMAT"`, `outcome_detail: "4"`, and `source_data.message: "Error de datos"`. Use these fields rather than treating every rejection as a generic availability error. * Provider code `0` means the submitted credential was not found. It is returned as `outcome_code: "DOCUMENT_NOT_FOUND"`, with `outcome_detail: "0"` and the original explanation in `source_data.message`. * Provider codes `1` and `10` mean the submitted credential data did not match the INE record. They are returned as `outcome_code: "NO_MATCH"`, with the provider code in `outcome_detail` and the original explanation in `source_data.message`. ## How to call it ```bash cURL theme={null} curl -X POST "https://verification.didit.me/v3/database-validation/" \ -H "x-api-key: YOUR_API_KEY" \ -F "issuing_state=MEX" \ -F "services=mex_ine_vigencia" \ -F "vendor_data=user-1234" ``` Every successful call returns HTTP `200`. The **`outcome_code`** field tells you what actually happened — distinguishing, for example, a real biometric mismatch (`BIOMETRIC_NO_MATCH`) from a selfie that could not be read (`BIOMETRIC_IMAGE_UNUSABLE`). The `status` shown is the default feature status; your configured [Partial Match / No Match actions](/core-technology/database-validation/database-validation-warnings) can override it. **`MATCH`** — The registry confirmed the identity and every checked field matched. ```json 200 OK — MATCH theme={null} { "request_id": "req_01H…", "status": "Approved", "issuing_state": "MEX", "match_type": "full_match", "validations": [ { "outcome_code": "MATCH", "service_id": "mex_ine_vigencia", "service_name": "Mexico - INE credential validity verification", "source_data": { "emission_number": "SAMPLE-12345", "emission_year": "sample_value", "expiration_date": "1990-01-01", "federal_district": "sample_value", "identification_number": "SAMPLE-ID-12345", "message": "sample_value", "message_code": "sample_value", "ocr": "sample_value", "registration_year": "sample_value", "validation_code": "SAMPLE-12345", "voter_number": "SAMPLE-12345" }, "validation": { "identification_number": "full_match" } } ] } ``` **`NO_MATCH`** — The registry returned no match for the submitted data. ```json 200 OK — NO_MATCH theme={null} { "request_id": "req_01H…", "status": "Declined", "issuing_state": "MEX", "match_type": "no_match", "validations": [ { "outcome_code": "NO_MATCH", "service_id": "mex_ine_vigencia", "service_name": "Mexico - INE credential validity verification", "source_data": { "identification_number": "NO_MATCH" }, "validation": { "identification_number": "no_match" } } ] } ``` ## Returned data The exact fields surfaced in `source_data` depend on what the registry returns. The generated example for `mex_ine_vigencia` currently documents this normalized shape: * `emission_number` * `emission_year` * `expiration_date` * `federal_district` * `identification_number` * `message` * `message_code` * `ocr` * `registration_year` * `validation_code` * `voter_number` ## Pricing & SLAs Mexico - INE credential validity verification queries are billed only when Didit receives a conclusive result from the validation source. * **Per-call price:** \$0.20 USD. * **Billing:** per successful query. You are not charged when the registry is unreachable, when required fields are missing, or when the request is rejected before reaching the source. * **Latency:** typical p95 \< 2 s. * **Availability:** 99.9% per quarter on Didit's side; downstream source availability varies by country and dataset. ## Continue reading * [Mexico Database Validation overview](/api-reference/database-validation/mexico) * [Database Validation overview](/core-technology/database-validation/overview) * [Outcome Codes](/core-technology/database-validation/database-validation-outcome-codes) # Netherlands Residential Source: https://docs.didit.me/api-reference/database-validation/netherlands/residential POST /v3/database-validation/ Verifies input data to a data source containing Government records, postal, and public records. Authoritative real-time identity lookup for Netherlands. Real-time lookup, pay-per-call.
Verifies input data to a data source containing Government records, postal, and public records. Didit exposes this service through `POST /v3/database-validation/` so you can verify the submitted data against the authoritative source and receive normalized match results. ## Coverage * **Coverage:** > 80% * **Country:** Netherlands * **Service ID:** `nld_residential` * **Data domain:** Address * **Category:** Residential ## Inputs | Field | Required | Example | | --------------------- | -------: | ------------------- | | `first_name` | Yes | `John` | | `last_name` | Yes | `Doe` | | `date_of_birth` | Yes | `1990-01-01` | | `address.street_1` | Yes | `123 Sample Street` | | `address.postal_code` | Yes | `10001` | | `national_id` | No | `SAMPLE-NID-12345` | | `address.street_2` | No | `Unit 4` | | `address.city` | No | `Sample City` | | `address.region` | No | `Sample State` | | `vendor_data` | No | `user-1234` | * **Required inputs:** `first_name`, `last_name`, `date_of_birth`, `address.street_1`, `address.postal_code` * **Optional inputs:** `national_id`, `address.street_2`, `address.city`, `address.region`, `vendor_data` * **Consent:** Not required * **Workflow availability:** Available in workflow * **Coverage:** > 80% * **Price:** \$0.90 per successful query ## Body parameters ISO 3166-1 alpha-3 country code for this database service. Example: `NLD` Array containing this service ID. Pinning the service keeps the request scoped to this exact database. Example: `nld_residential` Given name to validate. Example: `John` Family name to validate. Example: `Doe` Date of birth in `YYYY-MM-DD` format. Example: `1990-01-01` Structured residential address object. Use `street_1`, `street_2`, `city`, `region`, `postal_code`, and `country`. A complete legacy address string is still accepted but not recommended. Example: `{"street_1":"123 Sample Street","street_2":"Unit 4","city":"Sample City","region":"Sample State","postal_code":"10001","country":"US"}` National identity number for this service. Example: `SAMPLE-NID-12345` Your stable user reference for this person, such as your internal user ID. Didit uses it to link standalone checks to the same end user and reduce duplicate-detection noise. Example: `user-1234` ## Input rules & validation notes * For address services, send structured address fields instead of a single `address` string when possible. * `address.street_1` is the street address, including street number and street type. * `address.street_2` is apartment, unit, building, floor, or extra address line. Send it only when you have it. * `address.city` is city, suburb, district, locality, or neighborhood. * `address.region` is state, province, region, or town. * `address.postal_code` is postcode or postal code. * Address-based database services require at least street address and postal code; requests rejected before source lookup are not charged. ## How to call it ```bash cURL theme={null} curl -X POST "https://verification.didit.me/v3/database-validation/" \ -H "x-api-key: YOUR_API_KEY" \ -F "issuing_state=NLD" \ -F "services=nld_residential" \ -F "vendor_data=user-1234" \ -F "first_name=John" \ -F "last_name=Doe" \ -F "date_of_birth=1990-01-01" \ -F 'address={"street_1":"123 Sample Street","street_2":"Unit 4","city":"Sample City","region":"Sample State","postal_code":"10001","country":"US"}' ``` Every successful call returns HTTP `200`. The **`outcome_code`** field tells you what actually happened — distinguishing, for example, a real biometric mismatch (`BIOMETRIC_NO_MATCH`) from a selfie that could not be read (`BIOMETRIC_IMAGE_UNUSABLE`). The `status` shown is the default feature status; your configured [Partial Match / No Match actions](/core-technology/database-validation/database-validation-warnings) can override it. **`MATCH`** — The registry confirmed the identity and every checked field matched. ```json 200 OK — MATCH theme={null} { "request_id": "req_01H…", "status": "Approved", "issuing_state": "NLD", "match_type": "full_match", "validations": [ { "outcome_code": "MATCH", "service_id": "nld_residential", "service_name": "Netherlands Residential", "source_data": { "address": "123 Sample Street", "date_of_birth": "1990-01-01", "first_name": "John", "identification_number": "SAMPLE-ID-12345", "last_name": "Doe" }, "validation": { "address": "full_match", "date_of_birth": "full_match", "full_name": "full_match" } } ] } ``` **`PARTIAL_MATCH`** — The identification number was found but one or more personal fields (usually name or date of birth) did not fully match. ```json 200 OK — PARTIAL_MATCH theme={null} { "request_id": "req_01H…", "status": "In Review", "issuing_state": "NLD", "match_type": "partial_match", "validations": [ { "outcome_code": "PARTIAL_MATCH", "service_id": "nld_residential", "service_name": "Netherlands Residential", "source_data": { "address": "123 Sample Street", "date_of_birth": "1990-01-01", "first_name": "John", "identification_number": "SAMPLE-ID-12345", "last_name": "Doe" }, "validation": { "address": "full_match", "date_of_birth": "full_match", "full_name": "no_match" } } ] } ``` **`NO_MATCH`** — The registry returned no match for the submitted data. ```json 200 OK — NO_MATCH theme={null} { "request_id": "req_01H…", "status": "Declined", "issuing_state": "NLD", "match_type": "no_match", "validations": [ { "outcome_code": "NO_MATCH", "service_id": "nld_residential", "service_name": "Netherlands Residential", "source_data": { "address": "NO_MATCH", "date_of_birth": "NO_MATCH", "full_name": "NO_MATCH" }, "validation": { "address": "no_match", "date_of_birth": "no_match", "full_name": "no_match" } } ] } ``` ## Returned data The exact fields surfaced in `source_data` depend on what the registry returns. The generated example for `nld_residential` currently documents this normalized shape: * `address` * `date_of_birth` * `first_name` * `identification_number` * `last_name` ## Pricing & SLAs Netherlands Residential queries are billed only when Didit receives a conclusive result from the validation source. * **Per-call price:** \$0.90 USD. * **Billing:** per successful query. You are not charged when the registry is unreachable, when required fields are missing, or when the request is rejected before reaching the source. * **Latency:** typical p95 \< 2 s. * **Availability:** 99.9% per quarter on Didit's side; downstream source availability varies by country and dataset. ## Continue reading * [Netherlands Database Validation overview](/api-reference/database-validation/netherlands) * [Database Validation overview](/core-technology/database-validation/overview) * [Outcome Codes](/core-technology/database-validation/database-validation-outcome-codes) # DIA - New Zealand Births Source: https://docs.didit.me/api-reference/database-validation/new-zealand/births POST /v3/database-validation/ DIA Birth Certificate verification service. Authoritative real-time identity lookup for New Zealand. Real-time lookup, pay-per-call.
DIA Birth Certificate verification service. Didit exposes this service through `POST /v3/database-validation/` so you can verify the submitted data against the authoritative source and receive normalized match results. ## Coverage * **Coverage:** \~ 85% * **Country:** New Zealand * **Service ID:** `nzl_new_zealand_births` * **Data domain:** Identity * **Category:** BirthRecord ## Inputs | Field | Required | Example | | --------------- | -------: | ------------ | | `first_name` | Yes | `John` | | `last_name` | Yes | `Doe` | | `date_of_birth` | Yes | `1990-01-01` | | `vendor_data` | No | `user-1234` | * **Required inputs:** `first_name`, `last_name`, `date_of_birth` * **Optional inputs:** `vendor_data` * **Consent:** Required * **Workflow availability:** Available in workflow * **Coverage:** \~ 85% * **Price:** \$1.00 per successful query ## Body parameters ISO 3166-1 alpha-3 country code for this database service. Example: `NZL` Array containing this service ID. Pinning the service keeps the request scoped to this exact database. Example: `nzl_new_zealand_births` Explicit end-user consent for this service. Example: `true` Given name to validate. Example: `John` Family name to validate. Example: `Doe` Date of birth in `YYYY-MM-DD` format. Example: `1990-01-01` Your stable user reference for this person, such as your internal user ID. Didit uses it to link standalone checks to the same end user and reduce duplicate-detection noise. Example: `user-1234` ## Input rules & validation notes * Send the fields listed above exactly as captured from the user or document. * Didit validates required fields before calling the database. Requests rejected before source lookup are not charged. ## How to call it ```bash cURL theme={null} curl -X POST "https://verification.didit.me/v3/database-validation/" \ -H "x-api-key: YOUR_API_KEY" \ -F "issuing_state=NZL" \ -F "services=nzl_new_zealand_births" \ -F "vendor_data=user-1234" \ -F "consent=true" \ -F "first_name=John" \ -F "last_name=Doe" \ -F "date_of_birth=1990-01-01" ``` Every successful call returns HTTP `200`. The **`outcome_code`** field tells you what actually happened — distinguishing, for example, a real biometric mismatch (`BIOMETRIC_NO_MATCH`) from a selfie that could not be read (`BIOMETRIC_IMAGE_UNUSABLE`). The `status` shown is the default feature status; your configured [Partial Match / No Match actions](/core-technology/database-validation/database-validation-warnings) can override it. **`MATCH`** — The registry confirmed the identity and every checked field matched. ```json 200 OK — MATCH theme={null} { "request_id": "req_01H…", "status": "Approved", "issuing_state": "NZL", "match_type": "full_match", "validations": [ { "outcome_code": "MATCH", "service_id": "nzl_new_zealand_births", "service_name": "DIA - New Zealand Births", "source_data": { "date_of_birth": "1990-01-01", "first_name": "John", "last_name": "Doe" }, "validation": { "date_of_birth": "full_match", "full_name": "full_match" } } ] } ``` **`PARTIAL_MATCH`** — The identification number was found but one or more personal fields (usually name or date of birth) did not fully match. ```json 200 OK — PARTIAL_MATCH theme={null} { "request_id": "req_01H…", "status": "In Review", "issuing_state": "NZL", "match_type": "partial_match", "validations": [ { "outcome_code": "PARTIAL_MATCH", "service_id": "nzl_new_zealand_births", "service_name": "DIA - New Zealand Births", "source_data": { "date_of_birth": "1990-01-01", "first_name": "John", "last_name": "Doe" }, "validation": { "date_of_birth": "full_match", "full_name": "no_match" } } ] } ``` **`NO_MATCH`** — The registry returned no match for the submitted data. ```json 200 OK — NO_MATCH theme={null} { "request_id": "req_01H…", "status": "Declined", "issuing_state": "NZL", "match_type": "no_match", "validations": [ { "outcome_code": "NO_MATCH", "service_id": "nzl_new_zealand_births", "service_name": "DIA - New Zealand Births", "source_data": { "date_of_birth": "NO_MATCH", "full_name": "NO_MATCH" }, "validation": { "date_of_birth": "no_match", "full_name": "no_match" } } ] } ``` ## Returned data The exact fields surfaced in `source_data` depend on what the registry returns. The generated example for `nzl_new_zealand_births` currently documents this normalized shape: * `date_of_birth` * `first_name` * `last_name` ## Pricing & SLAs DIA - New Zealand Births queries are billed only when Didit receives a conclusive result from the validation source. * **Per-call price:** \$1.00 USD. * **Billing:** per successful query. You are not charged when the registry is unreachable, when required fields are missing, or when the request is rejected before reaching the source. * **Latency:** typical p95 \< 2 s. * **Availability:** 99.9% per quarter on Didit's side; downstream source availability varies by country and dataset. ## Continue reading * [New Zealand Database Validation overview](/api-reference/database-validation/new-zealand) * [Database Validation overview](/core-technology/database-validation/overview) * [Outcome Codes](/core-technology/database-validation/database-validation-outcome-codes) # DIA - New Zealand Citizenship Source: https://docs.didit.me/api-reference/database-validation/new-zealand/citizenship POST /v3/database-validation/ DIA Citizenship verification service. Authoritative real-time identity lookup for New Zealand. Real-time lookup, pay-per-call.
DIA Citizenship verification service. Didit exposes this service through `POST /v3/database-validation/` so you can verify the submitted data against the authoritative source and receive normalized match results. ## Coverage * **Coverage:** > 10% * **Country:** New Zealand * **Service ID:** `nzl_new_zealand_citizenship` * **Data domain:** Identity * **Category:** Citizenship ## Inputs | Field | Required | Example | | --------------- | -------: | ------------ | | `first_name` | Yes | `John` | | `last_name` | Yes | `Doe` | | `date_of_birth` | Yes | `1990-01-01` | | `vendor_data` | No | `user-1234` | * **Required inputs:** `first_name`, `last_name`, `date_of_birth` * **Optional inputs:** `vendor_data` * **Consent:** Required * **Workflow availability:** Available in workflow * **Coverage:** > 10% * **Price:** \$1.00 per successful query ## Body parameters ISO 3166-1 alpha-3 country code for this database service. Example: `NZL` Array containing this service ID. Pinning the service keeps the request scoped to this exact database. Example: `nzl_new_zealand_citizenship` Explicit end-user consent for this service. Example: `true` Given name to validate. Example: `John` Family name to validate. Example: `Doe` Date of birth in `YYYY-MM-DD` format. Example: `1990-01-01` Your stable user reference for this person, such as your internal user ID. Didit uses it to link standalone checks to the same end user and reduce duplicate-detection noise. Example: `user-1234` ## Input rules & validation notes * Send the fields listed above exactly as captured from the user or document. * Didit validates required fields before calling the database. Requests rejected before source lookup are not charged. ## How to call it ```bash cURL theme={null} curl -X POST "https://verification.didit.me/v3/database-validation/" \ -H "x-api-key: YOUR_API_KEY" \ -F "issuing_state=NZL" \ -F "services=nzl_new_zealand_citizenship" \ -F "vendor_data=user-1234" \ -F "consent=true" \ -F "first_name=John" \ -F "last_name=Doe" \ -F "date_of_birth=1990-01-01" ``` Every successful call returns HTTP `200`. The **`outcome_code`** field tells you what actually happened — distinguishing, for example, a real biometric mismatch (`BIOMETRIC_NO_MATCH`) from a selfie that could not be read (`BIOMETRIC_IMAGE_UNUSABLE`). The `status` shown is the default feature status; your configured [Partial Match / No Match actions](/core-technology/database-validation/database-validation-warnings) can override it. **`MATCH`** — The registry confirmed the identity and every checked field matched. ```json 200 OK — MATCH theme={null} { "request_id": "req_01H…", "status": "Approved", "issuing_state": "NZL", "match_type": "full_match", "validations": [ { "outcome_code": "MATCH", "service_id": "nzl_new_zealand_citizenship", "service_name": "DIA - New Zealand Citizenship", "source_data": { "date_of_birth": "1990-01-01", "first_name": "John", "last_name": "Doe" }, "validation": { "date_of_birth": "full_match", "full_name": "full_match" } } ] } ``` **`PARTIAL_MATCH`** — The identification number was found but one or more personal fields (usually name or date of birth) did not fully match. ```json 200 OK — PARTIAL_MATCH theme={null} { "request_id": "req_01H…", "status": "In Review", "issuing_state": "NZL", "match_type": "partial_match", "validations": [ { "outcome_code": "PARTIAL_MATCH", "service_id": "nzl_new_zealand_citizenship", "service_name": "DIA - New Zealand Citizenship", "source_data": { "date_of_birth": "1990-01-01", "first_name": "John", "last_name": "Doe" }, "validation": { "date_of_birth": "full_match", "full_name": "no_match" } } ] } ``` **`NO_MATCH`** — The registry returned no match for the submitted data. ```json 200 OK — NO_MATCH theme={null} { "request_id": "req_01H…", "status": "Declined", "issuing_state": "NZL", "match_type": "no_match", "validations": [ { "outcome_code": "NO_MATCH", "service_id": "nzl_new_zealand_citizenship", "service_name": "DIA - New Zealand Citizenship", "source_data": { "date_of_birth": "NO_MATCH", "full_name": "NO_MATCH" }, "validation": { "date_of_birth": "no_match", "full_name": "no_match" } } ] } ``` ## Returned data The exact fields surfaced in `source_data` depend on what the registry returns. The generated example for `nzl_new_zealand_citizenship` currently documents this normalized shape: * `date_of_birth` * `first_name` * `last_name` ## Pricing & SLAs DIA - New Zealand Citizenship queries are billed only when Didit receives a conclusive result from the validation source. * **Per-call price:** \$1.00 USD. * **Billing:** per successful query. You are not charged when the registry is unreachable, when required fields are missing, or when the request is rejected before reaching the source. * **Latency:** typical p95 \< 2 s. * **Availability:** 99.9% per quarter on Didit's side; downstream source availability varies by country and dataset. ## Continue reading * [New Zealand Database Validation overview](/api-reference/database-validation/new-zealand) * [Database Validation overview](/core-technology/database-validation/overview) * [Outcome Codes](/core-technology/database-validation/database-validation-outcome-codes) # New Zealand Death Check (BDM) Source: https://docs.didit.me/api-reference/database-validation/new-zealand/death-check POST /v3/database-validation/ The official New Zealand Birth, Deaths, Marriages Register. Authoritative real-time identity lookup for New Zealand. Real-time lookup, pay-per-call.
The official New Zealand Birth, Deaths, Marriages Register. Didit exposes this service through `POST /v3/database-validation/` so you can verify the submitted data against the authoritative source and receive normalized match results. ## Coverage * **Coverage:** 100%\* * **Country:** New Zealand * **Service ID:** `nzl_zealand_death_check` * **Data domain:** Other * **Category:** DeathRecord ## Inputs | Field | Required | Example | | --------------------- | -------: | ------------------- | | `first_name` | Yes | `John` | | `last_name` | Yes | `Doe` | | `date_of_birth` | Yes | `1990-01-01` | | `address.street_1` | Yes | `123 Sample Street` | | `address.postal_code` | Yes | `10001` | | `address.street_2` | No | `Unit 4` | | `address.city` | No | `Sample City` | | `address.region` | No | `Sample State` | | `vendor_data` | No | `user-1234` | * **Required inputs:** `first_name`, `last_name`, `date_of_birth`, `address.street_1`, `address.postal_code` * **Optional inputs:** `address.street_2`, `address.city`, `address.region`, `vendor_data` * **Consent:** Not required * **Workflow availability:** Available in workflow * **Coverage:** 100%\* * **Price:** \$0.16 per successful query ## Body parameters ISO 3166-1 alpha-3 country code for this database service. Example: `NZL` Array containing this service ID. Pinning the service keeps the request scoped to this exact database. Example: `nzl_zealand_death_check` Given name to validate. Example: `John` Family name to validate. Example: `Doe` Date of birth in `YYYY-MM-DD` format. Example: `1990-01-01` Structured residential address object. Use `street_1`, `street_2`, `city`, `region`, `postal_code`, and `country`. A complete legacy address string is still accepted but not recommended. Example: `{"street_1":"123 Sample Street","street_2":"Unit 4","city":"Sample City","region":"Sample State","postal_code":"10001","country":"US"}` Your stable user reference for this person, such as your internal user ID. Didit uses it to link standalone checks to the same end user and reduce duplicate-detection noise. Example: `user-1234` ## Input rules & validation notes * For address services, send structured address fields instead of a single `address` string when possible. * `address.street_1` is the street address, including street number and street type. * `address.street_2` is apartment, unit, building, floor, or extra address line. Send it only when you have it. * `address.city` is city, suburb, district, locality, or neighborhood. * `address.region` is state, province, region, or town. * `address.postal_code` is postcode or postal code. * Address-based database services require at least street address and postal code; requests rejected before source lookup are not charged. ## How to call it ```bash cURL theme={null} curl -X POST "https://verification.didit.me/v3/database-validation/" \ -H "x-api-key: YOUR_API_KEY" \ -F "issuing_state=NZL" \ -F "services=nzl_zealand_death_check" \ -F "vendor_data=user-1234" \ -F "first_name=John" \ -F "last_name=Doe" \ -F "date_of_birth=1990-01-01" \ -F 'address={"street_1":"123 Sample Street","street_2":"Unit 4","city":"Sample City","region":"Sample State","postal_code":"10001","country":"US"}' ``` Every successful call returns HTTP `200`. The **`outcome_code`** field tells you what actually happened — distinguishing, for example, a real biometric mismatch (`BIOMETRIC_NO_MATCH`) from a selfie that could not be read (`BIOMETRIC_IMAGE_UNUSABLE`). The `status` shown is the default feature status; your configured [Partial Match / No Match actions](/core-technology/database-validation/database-validation-warnings) can override it. **`MATCH`** — The registry confirmed the identity and every checked field matched. ```json 200 OK — MATCH theme={null} { "request_id": "req_01H…", "status": "Approved", "issuing_state": "NZL", "match_type": "full_match", "validations": [ { "outcome_code": "MATCH", "service_id": "nzl_zealand_death_check", "service_name": "New Zealand Death Check (BDM)", "source_data": { "address": "123 Sample Street", "address_match_score": "1.000", "city": "Sample City", "date_of_birth": "1990-01-01", "first_name": "John", "full_name": "John Doe", "last_name": "Doe", "name_match_score": "1.000", "postal_code": "10001", "state": "Sample State", "street": "sample_value" }, "validation": { "address": "full_match", "date_of_birth": "full_match", "full_name": "full_match" } } ] } ``` **`PARTIAL_MATCH`** — The identification number was found but one or more personal fields (usually name or date of birth) did not fully match. ```json 200 OK — PARTIAL_MATCH theme={null} { "request_id": "req_01H…", "status": "In Review", "issuing_state": "NZL", "match_type": "partial_match", "validations": [ { "outcome_code": "PARTIAL_MATCH", "service_id": "nzl_zealand_death_check", "service_name": "New Zealand Death Check (BDM)", "source_data": { "address": "123 Sample Street", "address_match_score": "1.000", "city": "Sample City", "date_of_birth": "1990-01-01", "first_name": "John", "full_name": "John Doe", "last_name": "Doe", "name_match_score": "1.000", "postal_code": "10001", "state": "Sample State", "street": "sample_value" }, "validation": { "address": "full_match", "date_of_birth": "full_match", "full_name": "no_match" } } ] } ``` **`NO_MATCH`** — The registry returned no match for the submitted data. ```json 200 OK — NO_MATCH theme={null} { "request_id": "req_01H…", "status": "Declined", "issuing_state": "NZL", "match_type": "no_match", "validations": [ { "outcome_code": "NO_MATCH", "service_id": "nzl_zealand_death_check", "service_name": "New Zealand Death Check (BDM)", "source_data": { "address": "NO_MATCH", "date_of_birth": "NO_MATCH", "full_name": "NO_MATCH" }, "validation": { "address": "no_match", "date_of_birth": "no_match", "full_name": "no_match" } } ] } ``` ## Returned data The exact fields surfaced in `source_data` depend on what the registry returns. The generated example for `nzl_zealand_death_check` currently documents this normalized shape: * `address` * `address_match_score` * `city` * `date_of_birth` * `first_name` * `full_name` * `last_name` * `name_match_score` * `postal_code` * `state` * `street` ## Pricing & SLAs New Zealand Death Check (BDM) queries are billed only when Didit receives a conclusive result from the validation source. * **Per-call price:** \$0.16 USD. * **Billing:** per successful query. You are not charged when the registry is unreachable, when required fields are missing, or when the request is rejected before reaching the source. * **Latency:** typical p95 \< 2 s. * **Availability:** 99.9% per quarter on Didit's side; downstream source availability varies by country and dataset. ## Continue reading * [New Zealand Database Validation overview](/api-reference/database-validation/new-zealand) * [Database Validation overview](/core-technology/database-validation/overview) * [Outcome Codes](/core-technology/database-validation/database-validation-outcome-codes) # New Zealand Drivers Licence (NZTA) Source: https://docs.didit.me/api-reference/database-validation/new-zealand/drivers-licence POST /v3/database-validation/ Verifies input data to the NZTA verification service. Authoritative real-time identity lookup for New Zealand. Real-time lookup, pay-per-call.
Verifies input data to the NZTA verification service. Didit exposes this service through `POST /v3/database-validation/` so you can verify the submitted data against the authoritative source and receive normalized match results. ## Coverage * **Coverage:** 100%\* * **Country:** New Zealand * **Service ID:** `nzl_zealand_drivers_licence` * **Data domain:** Document * **Category:** DriverLicence ## Inputs | Field | Required | Example | | ------------------------ | -------: | ----------------- | | `first_name` | Yes | `John` | | `last_name` | Yes | `Doe` | | `date_of_birth` | Yes | `1990-01-01` | | `driver_license_number` | Yes | `SAMPLE-DL-12345` | | `driver_license_version` | Yes | `1` | | `vendor_data` | No | `user-1234` | * **Required inputs:** `first_name`, `last_name`, `date_of_birth`, `driver_license_number`, `driver_license_version` * **Optional inputs:** `vendor_data` * **Consent:** Required * **Workflow availability:** Available in workflow * **Coverage:** 100%\* * **Price:** \$0.35 per successful query ## Body parameters ISO 3166-1 alpha-3 country code for this database service. Example: `NZL` Array containing this service ID. Pinning the service keeps the request scoped to this exact database. Example: `nzl_zealand_drivers_licence` Explicit end-user consent for this service. Example: `true` Given name to validate. Example: `John` Family name to validate. Example: `Doe` Date of birth in `YYYY-MM-DD` format. Example: `1990-01-01` Driver licence number. Example: `SAMPLE-DL-12345` `driver_license_version` value required by this database service. Example: `1` Your stable user reference for this person, such as your internal user ID. Didit uses it to link standalone checks to the same end user and reduce duplicate-detection noise. Example: `user-1234` ## Input rules & validation notes * Send the fields listed above exactly as captured from the user or document. * Didit validates required fields before calling the database. Requests rejected before source lookup are not charged. ## How to call it ```bash cURL theme={null} curl -X POST "https://verification.didit.me/v3/database-validation/" \ -H "x-api-key: YOUR_API_KEY" \ -F "issuing_state=NZL" \ -F "services=nzl_zealand_drivers_licence" \ -F "vendor_data=user-1234" \ -F "consent=true" \ -F "first_name=John" \ -F "last_name=Doe" \ -F "date_of_birth=1990-01-01" \ -F "driver_license_number=SAMPLE-DL-12345" \ -F "driver_license_version=1" ``` Every successful call returns HTTP `200`. The **`outcome_code`** field tells you what actually happened — distinguishing, for example, a real biometric mismatch (`BIOMETRIC_NO_MATCH`) from a selfie that could not be read (`BIOMETRIC_IMAGE_UNUSABLE`). The `status` shown is the default feature status; your configured [Partial Match / No Match actions](/core-technology/database-validation/database-validation-warnings) can override it. **`MATCH`** — The registry confirmed the identity and every checked field matched. ```json 200 OK — MATCH theme={null} { "request_id": "req_01H…", "status": "Approved", "issuing_state": "NZL", "match_type": "full_match", "validations": [ { "outcome_code": "MATCH", "service_id": "nzl_zealand_drivers_licence", "service_name": "New Zealand Drivers Licence (NZTA)", "source_data": { "date_of_birth": "1990-01-01", "first_name": "John", "full_name": "John Doe", "identification_number": "SAMPLE-ID-12345", "last_name": "Doe", "name_match_score": "1.000", "verifications": { "date_of_birth": true, "full_name": true, "identification_number": true } }, "validation": { "date_of_birth": "full_match", "full_name": "full_match", "identification_number": "full_match" } } ] } ``` **`PARTIAL_MATCH`** — The identification number was found but one or more personal fields (usually name or date of birth) did not fully match. ```json 200 OK — PARTIAL_MATCH theme={null} { "request_id": "req_01H…", "status": "In Review", "issuing_state": "NZL", "match_type": "partial_match", "validations": [ { "outcome_code": "PARTIAL_MATCH", "service_id": "nzl_zealand_drivers_licence", "service_name": "New Zealand Drivers Licence (NZTA)", "source_data": { "date_of_birth": "1990-01-01", "first_name": "John", "full_name": "John Doe", "identification_number": "SAMPLE-ID-12345", "last_name": "Doe", "name_match_score": "1.000", "verifications": { "date_of_birth": true, "full_name": false, "identification_number": true } }, "validation": { "date_of_birth": "full_match", "full_name": "no_match", "identification_number": "full_match" } } ] } ``` **`NO_MATCH`** — The registry returned no match for the submitted data. ```json 200 OK — NO_MATCH theme={null} { "request_id": "req_01H…", "status": "Declined", "issuing_state": "NZL", "match_type": "no_match", "validations": [ { "outcome_code": "NO_MATCH", "service_id": "nzl_zealand_drivers_licence", "service_name": "New Zealand Drivers Licence (NZTA)", "source_data": { "date_of_birth": "NO_MATCH", "full_name": "NO_MATCH", "identification_number": "NO_MATCH" }, "validation": { "date_of_birth": "no_match", "full_name": "no_match", "identification_number": "no_match" } } ] } ``` ## Returned data The exact fields surfaced in `source_data` depend on what the registry returns. The generated example for `nzl_zealand_drivers_licence` currently documents this normalized shape: * `date_of_birth` * `first_name` * `full_name` * `identification_number` * `last_name` * `name_match_score` ## Pricing & SLAs New Zealand Drivers Licence (NZTA) queries are billed only when Didit receives a conclusive result from the validation source. * **Per-call price:** \$0.35 USD. * **Billing:** per successful query. You are not charged when the registry is unreachable, when required fields are missing, or when the request is rejected before reaching the source. * **Latency:** typical p95 \< 2 s. * **Availability:** 99.9% per quarter on Didit's side; downstream source availability varies by country and dataset. ## Continue reading * [New Zealand Database Validation overview](/api-reference/database-validation/new-zealand) * [Database Validation overview](/core-technology/database-validation/overview) * [Outcome Codes](/core-technology/database-validation/database-validation-outcome-codes) # DIA - New Zealand Passport Source: https://docs.didit.me/api-reference/database-validation/new-zealand/passport POST /v3/database-validation/ DIA Passport verification service. Authoritative real-time identity lookup for New Zealand. Real-time lookup, pay-per-call.
DIA Passport verification service. Didit exposes this service through `POST /v3/database-validation/` so you can verify the submitted data against the authoritative source and receive normalized match results. ## Coverage * **Coverage:** 100%\* * **Country:** New Zealand * **Service ID:** `nzl_new_zealand_passport` * **Data domain:** Document * **Category:** Passport ## Inputs | Field | Required | Example | | -------------------------- | -------: | ------------------- | | `first_name` | Yes | `John` | | `last_name` | Yes | `Doe` | | `date_of_birth` | Yes | `1990-01-01` | | `passport_number` | Yes | `SAMPLE-PASS-12345` | | `passport_expiration_date` | Yes | `1990-01-01` | | `vendor_data` | No | `user-1234` | * **Required inputs:** `first_name`, `last_name`, `date_of_birth`, `passport_number`, `passport_expiration_date` * **Optional inputs:** `vendor_data` * **Consent:** Required * **Workflow availability:** Available in workflow * **Coverage:** 100%\* * **Price:** \$1.00 per successful query ## Body parameters ISO 3166-1 alpha-3 country code for this database service. Example: `NZL` Array containing this service ID. Pinning the service keeps the request scoped to this exact database. Example: `nzl_new_zealand_passport` Explicit end-user consent for this service. Example: `true` Given name to validate. Example: `John` Family name to validate. Example: `Doe` Date of birth in `YYYY-MM-DD` format. Example: `1990-01-01` Passport number. Example: `SAMPLE-PASS-12345` Passport expiration date in `YYYY-MM-DD` format. Example: `1990-01-01` Your stable user reference for this person, such as your internal user ID. Didit uses it to link standalone checks to the same end user and reduce duplicate-detection noise. Example: `user-1234` ## Input rules & validation notes * Send the fields listed above exactly as captured from the user or document. * Didit validates required fields before calling the database. Requests rejected before source lookup are not charged. ## How to call it ```bash cURL theme={null} curl -X POST "https://verification.didit.me/v3/database-validation/" \ -H "x-api-key: YOUR_API_KEY" \ -F "issuing_state=NZL" \ -F "services=nzl_new_zealand_passport" \ -F "vendor_data=user-1234" \ -F "consent=true" \ -F "first_name=John" \ -F "last_name=Doe" \ -F "date_of_birth=1990-01-01" \ -F "passport_number=SAMPLE-PASS-12345" \ -F "passport_expiration_date=1990-01-01" ``` Every successful call returns HTTP `200`. The **`outcome_code`** field tells you what actually happened — distinguishing, for example, a real biometric mismatch (`BIOMETRIC_NO_MATCH`) from a selfie that could not be read (`BIOMETRIC_IMAGE_UNUSABLE`). The `status` shown is the default feature status; your configured [Partial Match / No Match actions](/core-technology/database-validation/database-validation-warnings) can override it. **`MATCH`** — The registry confirmed the identity and every checked field matched. ```json 200 OK — MATCH theme={null} { "request_id": "req_01H…", "status": "Approved", "issuing_state": "NZL", "match_type": "full_match", "validations": [ { "outcome_code": "MATCH", "service_id": "nzl_new_zealand_passport", "service_name": "DIA - New Zealand Passport", "source_data": { "date_of_birth": "1990-01-01", "first_name": "John", "identification_number": "SAMPLE-ID-12345", "last_name": "Doe" }, "validation": { "date_of_birth": "full_match", "full_name": "full_match", "identification_number": "full_match" } } ] } ``` **`PARTIAL_MATCH`** — The identification number was found but one or more personal fields (usually name or date of birth) did not fully match. ```json 200 OK — PARTIAL_MATCH theme={null} { "request_id": "req_01H…", "status": "In Review", "issuing_state": "NZL", "match_type": "partial_match", "validations": [ { "outcome_code": "PARTIAL_MATCH", "service_id": "nzl_new_zealand_passport", "service_name": "DIA - New Zealand Passport", "source_data": { "date_of_birth": "1990-01-01", "first_name": "John", "identification_number": "SAMPLE-ID-12345", "last_name": "Doe" }, "validation": { "date_of_birth": "full_match", "full_name": "no_match", "identification_number": "full_match" } } ] } ``` **`NO_MATCH`** — The registry returned no match for the submitted data. ```json 200 OK — NO_MATCH theme={null} { "request_id": "req_01H…", "status": "Declined", "issuing_state": "NZL", "match_type": "no_match", "validations": [ { "outcome_code": "NO_MATCH", "service_id": "nzl_new_zealand_passport", "service_name": "DIA - New Zealand Passport", "source_data": { "date_of_birth": "NO_MATCH", "full_name": "NO_MATCH", "identification_number": "NO_MATCH" }, "validation": { "date_of_birth": "no_match", "full_name": "no_match", "identification_number": "no_match" } } ] } ``` ## Returned data The exact fields surfaced in `source_data` depend on what the registry returns. The generated example for `nzl_new_zealand_passport` currently documents this normalized shape: * `date_of_birth` * `first_name` * `identification_number` * `last_name` ## Pricing & SLAs DIA - New Zealand Passport queries are billed only when Didit receives a conclusive result from the validation source. * **Per-call price:** \$1.00 USD. * **Billing:** per successful query. You are not charged when the registry is unreachable, when required fields are missing, or when the request is rejected before reaching the source. * **Latency:** typical p95 \< 2 s. * **Availability:** 99.9% per quarter on Didit's side; downstream source availability varies by country and dataset. ## Continue reading * [New Zealand Database Validation overview](/api-reference/database-validation/new-zealand) * [Database Validation overview](/core-technology/database-validation/overview) * [Outcome Codes](/core-technology/database-validation/database-validation-outcome-codes) # Nigeria Bank Verification Number (BVN) Source: https://docs.didit.me/api-reference/database-validation/nigeria/bank-verification-number POST /v3/database-validation/ Verifies input data against the Nigerian Banking Industry database. Requires a selfie: the enrolment portrait held against the BVN is face-matched with it, and the record is only returned when the two are the same person. Authoritative real-time identity lookup for Nigeria. Real-time lookup, pay-per-call.
Verifies input data against the Nigerian Banking Industry database. Requires a selfie: the enrolment portrait held against the BVN is face-matched with it, and the record is only returned when the two are the same person. Didit exposes this service through `POST /v3/database-validation/` so you can verify the submitted data against the authoritative source and receive normalized match results. ## Coverage * **Coverage:** \~ 100% * **Country:** Nigeria * **Service ID:** `nga_bank_verification_number` * **Data domain:** Financial * **Category:** Banking ## Inputs | Field | Required | Example | | --------------- | -------: | --------------- | | `bvn` | Yes | `11111111111` | | `selfie` | Yes | `@./selfie.jpg` | | `first_name` | No | `John` | | `last_name` | No | `Doe` | | `date_of_birth` | No | `1990-01-01` | | `vendor_data` | No | `user-1234` | * **Required inputs:** `bvn`, `selfie` * **Optional inputs:** `first_name`, `last_name`, `date_of_birth`, `vendor_data` * **Consent:** Not required * **Workflow availability:** Available in workflow with field mapping * **Coverage:** \~ 100% * **Price:** \$0.35 per successful query In a workflow, `bvn` is not printed on an identity document, so no step produces it on its own. Collect it from a Questionnaire answer, a Document AI extraction field, or a value you send when you create the session, and map it on the Database Validation step. Until it is mapped the workflow editor shows this service disabled and names the missing input; at run time a missing input means the check is skipped before any query, so you are never billed for a database that could not be asked. ## Body parameters ISO 3166-1 alpha-3 country code for this database service. Example: `NGA` Array containing this service ID. Pinning the service keeps the request scoped to this exact database. Example: `nga_bank_verification_number` Bank Verification Number. Example: `11111111111` Selfie image file to upload for biometric database validation. Accepted formats: JPEG, PNG, or WebP. Example: `@./selfie.jpg` Given name to validate. Example: `John` Family name to validate. Example: `Doe` Date of birth in `YYYY-MM-DD` format. Example: `1990-01-01` Your stable user reference for this person, such as your internal user ID. Didit uses it to link standalone checks to the same end user and reduce duplicate-detection noise. Example: `user-1234` ## Input rules & validation notes * Nigerian Bank Verification Number (exactly 11 digits) * `bvn` must contain digits only; remove spaces, hyphens, and punctuation before sending the request. * `bvn` must be exactly 11 characters long. ## How to call it ```bash cURL theme={null} curl -X POST "https://verification.didit.me/v3/database-validation/" \ -H "x-api-key: YOUR_API_KEY" \ -F "issuing_state=NGA" \ -F "services=nga_bank_verification_number" \ -F "vendor_data=user-1234" \ -F "bvn=11111111111" \ -F "selfie=@./selfie.jpg" ``` Every successful call returns HTTP `200`. The **`outcome_code`** field tells you what actually happened — distinguishing, for example, a real biometric mismatch (`BIOMETRIC_NO_MATCH`) from a selfie that could not be read (`BIOMETRIC_IMAGE_UNUSABLE`). The `status` shown is the default feature status; your configured [Partial Match / No Match actions](/core-technology/database-validation/database-validation-warnings) can override it. **`MATCH`** — The registry confirmed the identity and every checked field matched. ```json 200 OK — MATCH theme={null} { "request_id": "req_01H…", "status": "Approved", "issuing_state": "NGA", "match_type": "full_match", "validations": [ { "outcome_code": "MATCH", "service_id": "nga_bank_verification_number", "service_name": "Nigeria Bank Verification Number (BVN)", "source_data": { "date_of_birth": "1990-01-01", "first_name": "John", "last_name": "Doe" }, "validation": { "identification_number": "full_match" } } ] } ``` **`BIOMETRIC_NO_MATCH`** — The face-match score was below the acceptance threshold - the selfie is not the same person as the registry photo. ```json 200 OK — BIOMETRIC_NO_MATCH theme={null} { "request_id": "req_01H…", "status": "Declined", "issuing_state": "NGA", "match_type": "no_match", "validations": [ { "outcome_code": "BIOMETRIC_NO_MATCH", "service_id": "nga_bank_verification_number", "service_name": "Nigeria Bank Verification Number (BVN)", "source_data": { "identification_number": "NO_MATCH" }, "validation": { "identification_number": "no_match" } } ] } ``` **`INCONCLUSIVE`** — The registry could not determine whether the person matches - the result is genuinely uncertain (they may or may not be in the registry). This is NOT a no-match and NOT a technical image problem; no field is asserted, so match\_type is null and the check is sent to review. ```json 200 OK — INCONCLUSIVE theme={null} { "request_id": "req_01H…", "status": "In Review", "issuing_state": "NGA", "match_type": null, "validations": [ { "outcome_code": "INCONCLUSIVE", "service_id": "nga_bank_verification_number", "service_name": "Nigeria Bank Verification Number (BVN)", "source_data": {}, "validation": {} } ] } ``` **`DOCUMENT_NOT_FOUND`** — The submitted document number does not correspond to any record in the registry. ```json 200 OK — DOCUMENT_NOT_FOUND theme={null} { "request_id": "req_01H…", "status": "Declined", "issuing_state": "NGA", "match_type": "no_match", "validations": [ { "outcome_code": "DOCUMENT_NOT_FOUND", "service_id": "nga_bank_verification_number", "service_name": "Nigeria Bank Verification Number (BVN)", "source_data": { "identification_number": "NO_MATCH" }, "validation": { "identification_number": "no_match" } } ] } ``` ## Returned data The exact fields surfaced in `source_data` depend on what the registry returns. The generated example for `nga_bank_verification_number` currently documents this normalized shape: * `date_of_birth` * `first_name` * `last_name` ## Pricing & SLAs Nigeria Bank Verification Number (BVN) queries are billed only when Didit receives a conclusive result from the validation source. * **Per-call price:** \$0.35 USD. * **Billing:** per successful query. You are not charged when the registry is unreachable, when required fields are missing, or when the request is rejected before reaching the source. * **Latency:** typical p95 \< 2 s. * **Availability:** 99.9% per quarter on Didit's side; downstream source availability varies by country and dataset. ## Continue reading * [Nigeria Database Validation overview](/api-reference/database-validation/nigeria) * [Database Validation overview](/core-technology/database-validation/overview) * [Outcome Codes](/core-technology/database-validation/database-validation-outcome-codes) # Nigeria National ID (NIMC) Source: https://docs.didit.me/api-reference/database-validation/nigeria/national-id POST /v3/database-validation/ Verifies data against the National Identity database. Authoritative real-time identity lookup for Nigeria. Real-time lookup, pay-per-call.
Verifies data against the National Identity database. Didit exposes this service through `POST /v3/database-validation/` so you can verify the submitted data against the authoritative source and receive normalized match results. ## Coverage * **Coverage:** \~ 100% * **Country:** Nigeria * **Service ID:** `nga_national_id` * **Data domain:** Identity * **Category:** NationalIDRegistry ## Inputs | Field | Required | Example | | --------------- | -------: | ------------- | | `first_name` | Yes | `John` | | `last_name` | Yes | `Doe` | | `national_id` | Yes | `11111111111` | | `date_of_birth` | No | `1990-01-01` | | `vendor_data` | No | `user-1234` | * **Required inputs:** `first_name`, `last_name`, `national_id` * **Optional inputs:** `date_of_birth`, `vendor_data` * **Consent:** Not required * **Workflow availability:** Available in workflow * **Coverage:** \~ 100% * **Price:** \$0.20 per successful query Not every document this service accepts carries the identifier it queries by. When the identifier is not extracted from the document the check is recorded as **not applicable** - no database is queried and you are not charged - which for some countries is a large share of real users. To cover them, also collect the identifier from a Questionnaire answer, a Document AI extraction field, or a value you send when you create the session, and map it on the Database Validation step. ## Body parameters ISO 3166-1 alpha-3 country code for this database service. Example: `NGA` Array containing this service ID. Pinning the service keeps the request scoped to this exact database. Example: `nga_national_id` Given name to validate. Example: `John` Family name to validate. Example: `Doe` National identity number for this service. Example: `11111111111` Date of birth in `YYYY-MM-DD` format. Example: `1990-01-01` Your stable user reference for this person, such as your internal user ID. Didit uses it to link standalone checks to the same end user and reduce duplicate-detection noise. Example: `user-1234` ## Input rules & validation notes * `first_name` must match `[A-Za-zÀ-ÖØ-öø-ÿ .'-]+`. * `national_id` must contain digits only; remove spaces, hyphens, and punctuation before sending the request. * `national_id` must be exactly 11 characters long. ## How to call it ```bash cURL theme={null} curl -X POST "https://verification.didit.me/v3/database-validation/" \ -H "x-api-key: YOUR_API_KEY" \ -F "issuing_state=NGA" \ -F "services=nga_national_id" \ -F "vendor_data=user-1234" \ -F "first_name=John" \ -F "last_name=Doe" \ -F "national_id=11111111111" ``` Every successful call returns HTTP `200`. The **`outcome_code`** field tells you what actually happened — distinguishing, for example, a real biometric mismatch (`BIOMETRIC_NO_MATCH`) from a selfie that could not be read (`BIOMETRIC_IMAGE_UNUSABLE`). The `status` shown is the default feature status; your configured [Partial Match / No Match actions](/core-technology/database-validation/database-validation-warnings) can override it. **`MATCH`** — The registry confirmed the identity and every checked field matched. ```json 200 OK — MATCH theme={null} { "request_id": "req_01H…", "status": "Approved", "issuing_state": "NGA", "match_type": "full_match", "validations": [ { "outcome_code": "MATCH", "service_id": "nga_national_id", "service_name": "Nigeria National ID (NIMC)", "source_data": { "first_name": "John", "full_name": "John Doe", "identification_number": "SAMPLE-ID-12345", "last_name": "Doe", "name_match_score": "1.000" }, "validation": { "full_name": "full_match", "identification_number": "full_match" } } ] } ``` **`PARTIAL_MATCH`** — The identification number was found but one or more personal fields (usually name or date of birth) did not fully match. ```json 200 OK — PARTIAL_MATCH theme={null} { "request_id": "req_01H…", "status": "In Review", "issuing_state": "NGA", "match_type": "partial_match", "validations": [ { "outcome_code": "PARTIAL_MATCH", "service_id": "nga_national_id", "service_name": "Nigeria National ID (NIMC)", "source_data": { "first_name": "John", "full_name": "John Doe", "identification_number": "SAMPLE-ID-12345", "last_name": "Doe", "name_match_score": "1.000" }, "validation": { "full_name": "no_match", "identification_number": "full_match" } } ] } ``` **`NO_MATCH`** — The registry returned no match for the submitted data. ```json 200 OK — NO_MATCH theme={null} { "request_id": "req_01H…", "status": "Declined", "issuing_state": "NGA", "match_type": "no_match", "validations": [ { "outcome_code": "NO_MATCH", "service_id": "nga_national_id", "service_name": "Nigeria National ID (NIMC)", "source_data": { "full_name": "NO_MATCH", "identification_number": "NO_MATCH" }, "validation": { "full_name": "no_match", "identification_number": "no_match" } } ] } ``` ## Returned data The exact fields surfaced in `source_data` depend on what the registry returns. The generated example for `nga_national_id` currently documents this normalized shape: * `first_name` * `full_name` * `identification_number` * `last_name` * `name_match_score` ## Pricing & SLAs Nigeria National ID (NIMC) queries are billed only when Didit receives a conclusive result from the validation source. * **Per-call price:** \$0.20 USD. * **Billing:** per successful query. You are not charged when the registry is unreachable, when required fields are missing, or when the request is rejected before reaching the source. * **Latency:** typical p95 \< 2 s. * **Availability:** 99.9% per quarter on Didit's side; downstream source availability varies by country and dataset. ## Continue reading * [Nigeria Database Validation overview](/api-reference/database-validation/nigeria) * [Database Validation overview](/core-technology/database-validation/overview) * [Outcome Codes](/core-technology/database-validation/database-validation-outcome-codes) # Norway Residential Source: https://docs.didit.me/api-reference/database-validation/norway/residential POST /v3/database-validation/ Verifies input data against the Norwegian Register service. Authoritative real-time identity lookup for Norway. Real-time lookup, pay-per-call.
Verifies input data against the Norwegian Register service. Didit exposes this service through `POST /v3/database-validation/` so you can verify the submitted data against the authoritative source and receive normalized match results. ## Coverage * **Coverage:** \~ 100% * **Country:** Norway * **Service ID:** `nor_residential` * **Data domain:** Address * **Category:** Residential ## Inputs | Field | Required | Example | | --------------------- | -------: | ---------------------- | | `first_name` | Yes | `John` | | `last_name` | Yes | `Doe` | | `date_of_birth` | Yes | `1990-01-01` | | `address.street_1` | Yes | `123 Sample Street` | | `address.postal_code` | Yes | `10001` | | `email` | No | `john.doe@example.com` | | `address.street_2` | No | `Unit 4` | | `address.city` | No | `Sample City` | | `address.region` | No | `Sample State` | | `vendor_data` | No | `user-1234` | * **Required inputs:** `first_name`, `last_name`, `date_of_birth`, `address.street_1`, `address.postal_code` * **Optional inputs:** `email`, `address.street_2`, `address.city`, `address.region`, `vendor_data` * **Consent:** Not required * **Workflow availability:** Available in workflow * **Coverage:** \~ 100% * **Price:** \$2.42 per successful query ## Body parameters ISO 3166-1 alpha-3 country code for this database service. Example: `NOR` Array containing this service ID. Pinning the service keeps the request scoped to this exact database. Example: `nor_residential` Given name to validate. Example: `John` Family name to validate. Example: `Doe` Date of birth in `YYYY-MM-DD` format. Example: `1990-01-01` Structured residential address object. Use `street_1`, `street_2`, `city`, `region`, `postal_code`, and `country`. A complete legacy address string is still accepted but not recommended. Example: `{"street_1":"123 Sample Street","street_2":"Unit 4","city":"Sample City","region":"Sample State","postal_code":"10001","country":"US"}` Email address. Example: `john.doe@example.com` Your stable user reference for this person, such as your internal user ID. Didit uses it to link standalone checks to the same end user and reduce duplicate-detection noise. Example: `user-1234` ## Input rules & validation notes * For address services, send structured address fields instead of a single `address` string when possible. * `address.street_1` is the street address, including street number and street type. * `address.street_2` is apartment, unit, building, floor, or extra address line. Send it only when you have it. * `address.city` is city, suburb, district, locality, or neighborhood. * `address.region` is state, province, region, or town. * `address.postal_code` is postcode or postal code. * Address-based database services require at least street address and postal code; requests rejected before source lookup are not charged. ## How to call it ```bash cURL theme={null} curl -X POST "https://verification.didit.me/v3/database-validation/" \ -H "x-api-key: YOUR_API_KEY" \ -F "issuing_state=NOR" \ -F "services=nor_residential" \ -F "vendor_data=user-1234" \ -F "first_name=John" \ -F "last_name=Doe" \ -F "date_of_birth=1990-01-01" \ -F 'address={"street_1":"123 Sample Street","street_2":"Unit 4","city":"Sample City","region":"Sample State","postal_code":"10001","country":"US"}' ``` Every successful call returns HTTP `200`. The **`outcome_code`** field tells you what actually happened — distinguishing, for example, a real biometric mismatch (`BIOMETRIC_NO_MATCH`) from a selfie that could not be read (`BIOMETRIC_IMAGE_UNUSABLE`). The `status` shown is the default feature status; your configured [Partial Match / No Match actions](/core-technology/database-validation/database-validation-warnings) can override it. **`MATCH`** — The registry confirmed the identity and every checked field matched. ```json 200 OK — MATCH theme={null} { "request_id": "req_01H…", "status": "Approved", "issuing_state": "NOR", "match_type": "full_match", "validations": [ { "outcome_code": "MATCH", "service_id": "nor_residential", "service_name": "Norway Residential", "source_data": { "address": "123 Sample Street", "date_of_birth": "1990-01-01", "first_name": "John", "last_name": "Doe" }, "validation": { "address": "full_match", "date_of_birth": "full_match", "full_name": "full_match" } } ] } ``` **`PARTIAL_MATCH`** — The identification number was found but one or more personal fields (usually name or date of birth) did not fully match. ```json 200 OK — PARTIAL_MATCH theme={null} { "request_id": "req_01H…", "status": "In Review", "issuing_state": "NOR", "match_type": "partial_match", "validations": [ { "outcome_code": "PARTIAL_MATCH", "service_id": "nor_residential", "service_name": "Norway Residential", "source_data": { "address": "123 Sample Street", "date_of_birth": "1990-01-01", "first_name": "John", "last_name": "Doe" }, "validation": { "address": "full_match", "date_of_birth": "full_match", "full_name": "no_match" } } ] } ``` **`NO_MATCH`** — The registry returned no match for the submitted data. ```json 200 OK — NO_MATCH theme={null} { "request_id": "req_01H…", "status": "Declined", "issuing_state": "NOR", "match_type": "no_match", "validations": [ { "outcome_code": "NO_MATCH", "service_id": "nor_residential", "service_name": "Norway Residential", "source_data": { "address": "NO_MATCH", "date_of_birth": "NO_MATCH", "full_name": "NO_MATCH" }, "validation": { "address": "no_match", "date_of_birth": "no_match", "full_name": "no_match" } } ] } ``` ## Returned data The exact fields surfaced in `source_data` depend on what the registry returns. The generated example for `nor_residential` currently documents this normalized shape: * `address` * `date_of_birth` * `first_name` * `last_name` ## Pricing & SLAs Norway Residential queries are billed only when Didit receives a conclusive result from the validation source. * **Per-call price:** \$2.42 USD. * **Billing:** per successful query. You are not charged when the registry is unreachable, when required fields are missing, or when the request is rejected before reaching the source. * **Latency:** typical p95 \< 2 s. * **Availability:** 99.9% per quarter on Didit's side; downstream source availability varies by country and dataset. ## Continue reading * [Norway Database Validation overview](/api-reference/database-validation/norway) * [Database Validation overview](/core-technology/database-validation/overview) * [Outcome Codes](/core-technology/database-validation/database-validation-outcome-codes) # Panama - Cédula with biometric face-match (SIB) Source: https://docs.didit.me/api-reference/database-validation/panama/sib POST /v3/database-validation/ Verifies Panamanian Cédula with biometric face-match against the Tribunal Electoral SIB biometric service. Standard tier. Authoritative real-time identity lookup for Panama. Real-time lookup, pay-per-call.
Verifies Panamanian Cédula with biometric face-match against the Tribunal Electoral SIB biometric service. Standard tier. Didit exposes this service through `POST /v3/database-validation/` so you can verify the submitted data against the authoritative source and receive normalized match results. ## Coverage * **Coverage:** — * **Country:** Panama * **Service ID:** `pan_cedula_sib` * **Data domain:** Identity * **Category:** NationalIDRegistry ## Inputs | Field | Required | Example | | ----------------- | -------: | ------------------ | | `personal_number` | Yes | `SAMPLE-PER-12345` | | `selfie` | Yes | `@./selfie.jpg` | | `vendor_data` | No | `user-1234` | * **Required inputs:** `personal_number`, `selfie` * **Optional inputs:** `vendor_data` * **Consent:** Not required * **Workflow availability:** Available in workflow * **Coverage:** — * **Price:** \$0.75 per successful query ## Body parameters ISO 3166-1 alpha-3 country code for this database service. Example: `PAN` Array containing this service ID. Pinning the service keeps the request scoped to this exact database. Example: `pan_cedula_sib` Country-specific personal identity number. Example: `SAMPLE-PER-12345` Selfie image file to upload for biometric database validation. Accepted formats: JPEG, PNG, or WebP. Example: `@./selfie.jpg` Your stable user reference for this person, such as your internal user ID. Didit uses it to link standalone checks to the same end user and reduce duplicate-detection noise. Example: `user-1234` ## Input rules & validation notes * Panamanian Cédula (min 5 characters) * `personal_number` must be 5-20 characters long. * `personal_number` must use uppercase letters. * `personal_number` must match `(?:\d{1,2}(?:-?(?:AV|PI))?|PE|E|N)[\d-]*`. ## How to call it ```bash cURL theme={null} curl -X POST "https://verification.didit.me/v3/database-validation/" \ -H "x-api-key: YOUR_API_KEY" \ -F "issuing_state=PAN" \ -F "services=pan_cedula_sib" \ -F "vendor_data=user-1234" \ -F "personal_number=SAMPLE-PER-12345" \ -F "selfie=@./selfie.jpg" ``` Every successful call returns HTTP `200`. The **`outcome_code`** field tells you what actually happened — distinguishing, for example, a real biometric mismatch (`BIOMETRIC_NO_MATCH`) from a selfie that could not be read (`BIOMETRIC_IMAGE_UNUSABLE`). The `status` shown is the default feature status; your configured [Partial Match / No Match actions](/core-technology/database-validation/database-validation-warnings) can override it. **`MATCH`** — The registry confirmed the identity and every checked field matched. ```json 200 OK — MATCH theme={null} { "request_id": "req_01H…", "status": "Approved", "issuing_state": "PAN", "match_type": "full_match", "validations": [ { "outcome_code": "MATCH", "service_id": "pan_cedula_sib", "service_name": "Panama - Cédula with biometric face-match (SIB)", "source_data": { "identification_number": "SAMPLE-ID-12345" }, "validation": { "identification_number": "full_match" } } ] } ``` **`NO_MATCH`** — The registry returned no match for the submitted data. ```json 200 OK — NO_MATCH theme={null} { "request_id": "req_01H…", "status": "Declined", "issuing_state": "PAN", "match_type": "no_match", "validations": [ { "outcome_code": "NO_MATCH", "service_id": "pan_cedula_sib", "service_name": "Panama - Cédula with biometric face-match (SIB)", "source_data": { "identification_number": "NO_MATCH" }, "validation": { "identification_number": "no_match" } } ] } ``` **`BIOMETRIC_NO_MATCH`** — The face-match score was below the acceptance threshold - the selfie is not the same person as the registry photo. ```json 200 OK — BIOMETRIC_NO_MATCH theme={null} { "request_id": "req_01H…", "status": "Declined", "issuing_state": "PAN", "match_type": "no_match", "validations": [ { "outcome_code": "BIOMETRIC_NO_MATCH", "service_id": "pan_cedula_sib", "service_name": "Panama - Cédula with biometric face-match (SIB)", "source_data": { "identification_number": "NO_MATCH" }, "validation": { "identification_number": "no_match" } } ] } ``` **`BIOMETRIC_IMAGE_UNUSABLE`** — The selfie could not be processed (empty, no face, low quality, or the registry could not read it). Prompt the user to retake the selfie. ```json 200 OK — BIOMETRIC_IMAGE_UNUSABLE theme={null} { "request_id": "req_01H…", "status": "In Review", "issuing_state": "PAN", "match_type": "no_match", "validations": [ { "outcome_code": "BIOMETRIC_IMAGE_UNUSABLE", "service_id": "pan_cedula_sib", "service_name": "Panama - Cédula with biometric face-match (SIB)", "source_data": { "identification_number": "NO_MATCH" }, "validation": { "identification_number": "no_match" } } ] } ``` **`DECEASED`** — The identity matched, but the registry flags the person as deceased. ```json 200 OK — DECEASED theme={null} { "request_id": "req_01H…", "status": "In Review", "issuing_state": "PAN", "match_type": "full_match", "validations": [ { "outcome_code": "DECEASED", "service_id": "pan_cedula_sib", "service_name": "Panama - Cédula with biometric face-match (SIB)", "source_data": { "identification_number": "SAMPLE-ID-12345" }, "validation": { "identification_number": "full_match" } } ] } ``` ## Returned data The exact fields surfaced in `source_data` depend on what the registry returns. The generated example for `pan_cedula_sib` currently documents this normalized shape: * `identification_number` ## Pricing & SLAs Panama - Cédula with biometric face-match (SIB) queries are billed only when Didit receives a conclusive result from the validation source. * **Per-call price:** \$0.75 USD. * **Billing:** per successful query. You are not charged when the registry is unreachable, when required fields are missing, or when the request is rejected before reaching the source. * **Latency:** typical p95 \< 2 s. * **Availability:** 99.9% per quarter on Didit's side; downstream source availability varies by country and dataset. ## Continue reading * [Panama Database Validation overview](/api-reference/database-validation/panama) * [Database Validation overview](/core-technology/database-validation/overview) * [Outcome Codes](/core-technology/database-validation/database-validation-outcome-codes) # Panama - Cédula with biometric face-match (SIB Plus, elevated tier) Source: https://docs.didit.me/api-reference/database-validation/panama/sib-plus POST /v3/database-validation/ Verifies Panamanian Cédula with biometric face-match — elevated-tier SIB Plus. Same data source as the standard SIB tier with stronger biometric thresholds and richer match metadata. Authoritative real-time identity lookup for Panama. Real-time lookup, pay-per-call.
Verifies Panamanian Cédula with biometric face-match — elevated-tier SIB Plus. Same data source as the standard SIB tier with stronger biometric thresholds and richer match metadata. Didit exposes this service through `POST /v3/database-validation/` so you can verify the submitted data against the authoritative source and receive normalized match results. ## Coverage * **Coverage:** — * **Country:** Panama * **Service ID:** `pan_cedula_sib_plus` * **Data domain:** Identity * **Category:** NationalIDRegistry ## Inputs | Field | Required | Example | | ----------------- | -------: | ------------------ | | `personal_number` | Yes | `SAMPLE-PER-12345` | | `selfie` | Yes | `@./selfie.jpg` | | `vendor_data` | No | `user-1234` | * **Required inputs:** `personal_number`, `selfie` * **Optional inputs:** `vendor_data` * **Consent:** Not required * **Workflow availability:** Available in workflow * **Coverage:** — * **Price:** \$1.50 per successful query ## Body parameters ISO 3166-1 alpha-3 country code for this database service. Example: `PAN` Array containing this service ID. Pinning the service keeps the request scoped to this exact database. Example: `pan_cedula_sib_plus` Country-specific personal identity number. Example: `SAMPLE-PER-12345` Selfie image file to upload for biometric database validation. Accepted formats: JPEG, PNG, or WebP. Example: `@./selfie.jpg` Your stable user reference for this person, such as your internal user ID. Didit uses it to link standalone checks to the same end user and reduce duplicate-detection noise. Example: `user-1234` ## Input rules & validation notes * Panamanian Cédula (min 5 characters) * `personal_number` must be 5-20 characters long. * `personal_number` must use uppercase letters. * `personal_number` must match `(?:\d{1,2}(?:-?(?:AV|PI))?|PE|E|N)[\d-]*`. ## How to call it ```bash cURL theme={null} curl -X POST "https://verification.didit.me/v3/database-validation/" \ -H "x-api-key: YOUR_API_KEY" \ -F "issuing_state=PAN" \ -F "services=pan_cedula_sib_plus" \ -F "vendor_data=user-1234" \ -F "personal_number=SAMPLE-PER-12345" \ -F "selfie=@./selfie.jpg" ``` Every successful call returns HTTP `200`. The **`outcome_code`** field tells you what actually happened — distinguishing, for example, a real biometric mismatch (`BIOMETRIC_NO_MATCH`) from a selfie that could not be read (`BIOMETRIC_IMAGE_UNUSABLE`). The `status` shown is the default feature status; your configured [Partial Match / No Match actions](/core-technology/database-validation/database-validation-warnings) can override it. **`MATCH`** — The registry confirmed the identity and every checked field matched. ```json 200 OK — MATCH theme={null} { "request_id": "req_01H…", "status": "Approved", "issuing_state": "PAN", "match_type": "full_match", "validations": [ { "outcome_code": "MATCH", "service_id": "pan_cedula_sib_plus", "service_name": "Panama - Cédula with biometric face-match (SIB Plus, elevated tier)", "source_data": { "date_of_birth": "1990-01-01", "expiration_date": "1990-01-01", "full_name": "John Doe", "gender": "M", "identification_number": "SAMPLE-ID-12345", "issue_date": "1990-01-01", "last_name": "Doe", "place_of_birth": "sample_value", "signature": "sample_value" }, "validation": { "identification_number": "full_match" } } ] } ``` **`NO_MATCH`** — The registry returned no match for the submitted data. ```json 200 OK — NO_MATCH theme={null} { "request_id": "req_01H…", "status": "Declined", "issuing_state": "PAN", "match_type": "no_match", "validations": [ { "outcome_code": "NO_MATCH", "service_id": "pan_cedula_sib_plus", "service_name": "Panama - Cédula with biometric face-match (SIB Plus, elevated tier)", "source_data": { "identification_number": "NO_MATCH" }, "validation": { "identification_number": "no_match" } } ] } ``` **`BIOMETRIC_NO_MATCH`** — The face-match score was below the acceptance threshold - the selfie is not the same person as the registry photo. ```json 200 OK — BIOMETRIC_NO_MATCH theme={null} { "request_id": "req_01H…", "status": "Declined", "issuing_state": "PAN", "match_type": "no_match", "validations": [ { "outcome_code": "BIOMETRIC_NO_MATCH", "service_id": "pan_cedula_sib_plus", "service_name": "Panama - Cédula with biometric face-match (SIB Plus, elevated tier)", "source_data": { "identification_number": "NO_MATCH" }, "validation": { "identification_number": "no_match" } } ] } ``` **`BIOMETRIC_IMAGE_UNUSABLE`** — The selfie could not be processed (empty, no face, low quality, or the registry could not read it). Prompt the user to retake the selfie. ```json 200 OK — BIOMETRIC_IMAGE_UNUSABLE theme={null} { "request_id": "req_01H…", "status": "In Review", "issuing_state": "PAN", "match_type": "no_match", "validations": [ { "outcome_code": "BIOMETRIC_IMAGE_UNUSABLE", "service_id": "pan_cedula_sib_plus", "service_name": "Panama - Cédula with biometric face-match (SIB Plus, elevated tier)", "source_data": { "identification_number": "NO_MATCH" }, "validation": { "identification_number": "no_match" } } ] } ``` **`DECEASED`** — The identity matched, but the registry flags the person as deceased. ```json 200 OK — DECEASED theme={null} { "request_id": "req_01H…", "status": "In Review", "issuing_state": "PAN", "match_type": "full_match", "validations": [ { "outcome_code": "DECEASED", "service_id": "pan_cedula_sib_plus", "service_name": "Panama - Cédula with biometric face-match (SIB Plus, elevated tier)", "source_data": { "date_of_birth": "1990-01-01", "expiration_date": "1990-01-01", "full_name": "John Doe", "gender": "M", "identification_number": "SAMPLE-ID-12345", "issue_date": "1990-01-01", "last_name": "Doe", "place_of_birth": "sample_value", "signature": "sample_value" }, "validation": { "identification_number": "full_match" } } ] } ``` ## Returned data The exact fields surfaced in `source_data` depend on what the registry returns. The generated example for `pan_cedula_sib_plus` currently documents this normalized shape: * `date_of_birth` * `expiration_date` * `full_name` * `gender` * `identification_number` * `issue_date` * `last_name` * `place_of_birth` * `signature` ## Pricing & SLAs Panama - Cédula with biometric face-match (SIB Plus, elevated tier) queries are billed only when Didit receives a conclusive result from the validation source. * **Per-call price:** \$1.50 USD. * **Billing:** per successful query. You are not charged when the registry is unreachable, when required fields are missing, or when the request is rejected before reaching the source. * **Latency:** typical p95 \< 2 s. * **Availability:** 99.9% per quarter on Didit's side; downstream source availability varies by country and dataset. ## Continue reading * [Panama Database Validation overview](/api-reference/database-validation/panama) * [Database Validation overview](/core-technology/database-validation/overview) * [Outcome Codes](/core-technology/database-validation/database-validation-outcome-codes) # Paraguay - CI verification Source: https://docs.didit.me/api-reference/database-validation/paraguay/cedula POST /v3/database-validation/ Verifies Paraguayan Cédula data against Registro del Estado Civil government records. Authoritative real-time identity lookup for Paraguay. Real-time lookup, pay-per-call.
Verifies Paraguayan Cédula data against Registro del Estado Civil government records. Didit exposes this service through `POST /v3/database-validation/` so you can verify the submitted data against the authoritative source and receive normalized match results. ## Coverage * **Coverage:** 90-95% * **Country:** Paraguay * **Service ID:** `pry_cedula` * **Data domain:** Identity * **Category:** NationalIDRegistry ## Inputs | Field | Required | Example | | ----------------- | -------: | ----------- | | `document_number` | Yes | `111111` | | `first_name` | No | `John` | | `last_name` | No | `Doe` | | `vendor_data` | No | `user-1234` | * **Required inputs:** `document_number` * **Optional inputs:** `first_name`, `last_name`, `vendor_data` * **Consent:** Not required * **Workflow availability:** Available in workflow * **Coverage:** 90-95% * **Price:** \$0.20 per successful query ## Body parameters ISO 3166-1 alpha-3 country code for this database service. Example: `PRY` Array containing this service ID. Pinning the service keeps the request scoped to this exact database. Example: `pry_cedula` Document number extracted from or provided by the user. Example: `111111` Given name to validate. Example: `John` Family name to validate. Example: `Doe` Your stable user reference for this person, such as your internal user ID. Didit uses it to link standalone checks to the same end user and reduce duplicate-detection noise. Example: `user-1234` ## Input rules & validation notes * Paraguayan CI (6-10 digits) * `document_number` must contain digits only; remove spaces, hyphens, and punctuation before sending the request. * `document_number` must be 6-10 characters long. ## How to call it ```bash cURL theme={null} curl -X POST "https://verification.didit.me/v3/database-validation/" \ -H "x-api-key: YOUR_API_KEY" \ -F "issuing_state=PRY" \ -F "services=pry_cedula" \ -F "vendor_data=user-1234" \ -F "document_number=111111" ``` Every successful call returns HTTP `200`. The **`outcome_code`** field tells you what actually happened — distinguishing, for example, a real biometric mismatch (`BIOMETRIC_NO_MATCH`) from a selfie that could not be read (`BIOMETRIC_IMAGE_UNUSABLE`). The `status` shown is the default feature status; your configured [Partial Match / No Match actions](/core-technology/database-validation/database-validation-warnings) can override it. **`MATCH`** — The registry confirmed the identity and every checked field matched. ```json 200 OK — MATCH theme={null} { "request_id": "req_01H…", "status": "Approved", "issuing_state": "PRY", "match_type": "full_match", "validations": [ { "outcome_code": "MATCH", "service_id": "pry_cedula", "service_name": "Paraguay - CI verification", "source_data": { "first_name": "John", "full_name": "John Doe", "identification_number": "SAMPLE-ID-12345", "last_name": "Doe" }, "validation": { "identification_number": "full_match" } } ] } ``` **`NO_MATCH`** — The registry returned no match for the submitted data. ```json 200 OK — NO_MATCH theme={null} { "request_id": "req_01H…", "status": "Declined", "issuing_state": "PRY", "match_type": "no_match", "validations": [ { "outcome_code": "NO_MATCH", "service_id": "pry_cedula", "service_name": "Paraguay - CI verification", "source_data": { "identification_number": "NO_MATCH" }, "validation": { "identification_number": "no_match" } } ] } ``` ## Returned data The exact fields surfaced in `source_data` depend on what the registry returns. The generated example for `pry_cedula` currently documents this normalized shape: * `first_name` * `full_name` * `identification_number` * `last_name` ## Pricing & SLAs Paraguay - CI verification queries are billed only when Didit receives a conclusive result from the validation source. * **Per-call price:** \$0.20 USD. * **Billing:** per successful query. You are not charged when the registry is unreachable, when required fields are missing, or when the request is rejected before reaching the source. * **Latency:** typical p95 \< 2 s. * **Availability:** 99.9% per quarter on Didit's side; downstream source availability varies by country and dataset. ## Continue reading * [Paraguay Database Validation overview](/api-reference/database-validation/paraguay) * [Database Validation overview](/core-technology/database-validation/overview) * [Outcome Codes](/core-technology/database-validation/database-validation-outcome-codes) # Peru - DNI verification Source: https://docs.didit.me/api-reference/database-validation/peru/dni POST /v3/database-validation/ Verifies Peruvian DNI against the RENIEC civil registry. Authoritative real-time identity lookup for Peru. Real-time lookup, pay-per-call.
Verifies Peruvian DNI against the RENIEC civil registry. Didit exposes this service through `POST /v3/database-validation/` so you can verify the submitted data against the authoritative source and receive normalized match results. ## Coverage * **Coverage:** — * **Country:** Peru * **Service ID:** `per_dni` * **Data domain:** Identity * **Category:** NationalIDRegistry ## Inputs | Field | Required | Example | | ----------------- | -------: | ----------- | | `personal_number` | Yes | `11111111` | | `first_name` | No | `John` | | `last_name` | No | `Doe` | | `vendor_data` | No | `user-1234` | * **Required inputs:** `personal_number` * **Optional inputs:** `first_name`, `last_name`, `vendor_data` * **Consent:** Not required * **Workflow availability:** Available in workflow * **Coverage:** — * **Price:** \$0.20 per successful query ## Body parameters ISO 3166-1 alpha-3 country code for this database service. Example: `PER` Array containing this service ID. Pinning the service keeps the request scoped to this exact database. Example: `per_dni` Country-specific personal identity number. Example: `11111111` Given name to validate. Example: `John` Family name to validate. Example: `Doe` Your stable user reference for this person, such as your internal user ID. Didit uses it to link standalone checks to the same end user and reduce duplicate-detection noise. Example: `user-1234` ## Input rules & validation notes * Peruvian DNI (exactly 8 digits) * `personal_number` must contain digits only; remove spaces, hyphens, and punctuation before sending the request. * `personal_number` must be exactly 8 characters long. ## How to call it ```bash cURL theme={null} curl -X POST "https://verification.didit.me/v3/database-validation/" \ -H "x-api-key: YOUR_API_KEY" \ -F "issuing_state=PER" \ -F "services=per_dni" \ -F "vendor_data=user-1234" \ -F "personal_number=11111111" ``` Every successful call returns HTTP `200`. The **`outcome_code`** field tells you what actually happened — distinguishing, for example, a real biometric mismatch (`BIOMETRIC_NO_MATCH`) from a selfie that could not be read (`BIOMETRIC_IMAGE_UNUSABLE`). The `status` shown is the default feature status; your configured [Partial Match / No Match actions](/core-technology/database-validation/database-validation-warnings) can override it. **`MATCH`** — The registry confirmed the identity and every checked field matched. ```json 200 OK — MATCH theme={null} { "request_id": "req_01H…", "status": "Approved", "issuing_state": "PER", "match_type": "full_match", "validations": [ { "outcome_code": "MATCH", "service_id": "per_dni", "service_name": "Peru - DNI verification", "source_data": { "first_name": "John", "identification_number": "SAMPLE-ID-12345", "last_name": "Doe", "maternal_name": "Doe Maternal", "paternal_name": "Doe Paternal", "verification_letter": "G", "verification_number": 2 }, "validation": { "identification_number": "full_match" } } ] } ``` **`NO_MATCH`** — The registry returned no match for the submitted data. ```json 200 OK — NO_MATCH theme={null} { "request_id": "req_01H…", "status": "Declined", "issuing_state": "PER", "match_type": "no_match", "validations": [ { "outcome_code": "NO_MATCH", "service_id": "per_dni", "service_name": "Peru - DNI verification", "source_data": { "identification_number": "NO_MATCH" }, "validation": { "identification_number": "no_match" } } ] } ``` **`DOCUMENT_NOT_FOUND`** — The submitted document number does not correspond to any record in the registry. ```json 200 OK — DOCUMENT_NOT_FOUND theme={null} { "request_id": "req_01H…", "status": "Declined", "issuing_state": "PER", "match_type": "no_match", "validations": [ { "outcome_code": "DOCUMENT_NOT_FOUND", "service_id": "per_dni", "service_name": "Peru - DNI verification", "source_data": { "identification_number": "NO_MATCH" }, "validation": { "identification_number": "no_match" } } ] } ``` ## Returned data The exact fields surfaced in `source_data` depend on what the registry returns. The generated example for `per_dni` currently documents this normalized shape: * `first_name` * `identification_number` * `last_name` * `maternal_name` * `paternal_name` * `verification_letter` * `verification_number` ## Pricing & SLAs Peru - DNI verification queries are billed only when Didit receives a conclusive result from the validation source. * **Per-call price:** \$0.20 USD. * **Billing:** per successful query. You are not charged when the registry is unreachable, when required fields are missing, or when the request is rejected before reaching the source. * **Latency:** typical p95 \< 2 s. * **Availability:** 99.9% per quarter on Didit's side; downstream source availability varies by country and dataset. ## Continue reading * [Peru Database Validation overview](/api-reference/database-validation/peru) * [Database Validation overview](/core-technology/database-validation/overview) * [Outcome Codes](/core-technology/database-validation/database-validation-outcome-codes) # Peru Tax Registration (SUNAT) Source: https://docs.didit.me/api-reference/database-validation/peru/tax-registration POST /v3/database-validation/ Verifies input data against SUNAT. Authoritative real-time identity lookup for Peru. Real-time lookup, pay-per-call.
Verifies input data against SUNAT. Didit exposes this service through `POST /v3/database-validation/` so you can verify the submitted data against the authoritative source and receive normalized match results. ## Coverage * **Coverage:** > 90% * **Country:** Peru * **Service ID:** `per_tax_registration` * **Data domain:** Financial * **Category:** TaxRegistry ## Inputs | Field | Required | Example | | ----------------- | -------: | ------------ | | `first_name` | Yes | `John` | | `last_name` | Yes | `Doe` | | `date_of_birth` | Yes | `1990-01-01` | | `personal_number` | Yes | `11111111` | | `vendor_data` | No | `user-1234` | * **Required inputs:** `first_name`, `last_name`, `date_of_birth`, `personal_number` * **Optional inputs:** `vendor_data` * **Consent:** Not required * **Workflow availability:** Available in workflow * **Coverage:** > 90% * **Price:** \$1.75 per successful query Not every document this service accepts carries the identifier it queries by. When the identifier is not extracted from the document the check is recorded as **not applicable** - no database is queried and you are not charged - which for some countries is a large share of real users. To cover them, also collect the identifier from a Questionnaire answer, a Document AI extraction field, or a value you send when you create the session, and map it on the Database Validation step. ## Body parameters ISO 3166-1 alpha-3 country code for this database service. Example: `PER` Array containing this service ID. Pinning the service keeps the request scoped to this exact database. Example: `per_tax_registration` Given name to validate. Example: `John` Family name to validate. Example: `Doe` Date of birth in `YYYY-MM-DD` format. Example: `1990-01-01` Country-specific personal identity number. Example: `11111111` Your stable user reference for this person, such as your internal user ID. Didit uses it to link standalone checks to the same end user and reduce duplicate-detection noise. Example: `user-1234` ## Input rules & validation notes * Peruvian DNI (exactly 8 digits) * `personal_number` must contain digits only; remove spaces, hyphens, and punctuation before sending the request. * `personal_number` must be exactly 8 characters long. ## How to call it ```bash cURL theme={null} curl -X POST "https://verification.didit.me/v3/database-validation/" \ -H "x-api-key: YOUR_API_KEY" \ -F "issuing_state=PER" \ -F "services=per_tax_registration" \ -F "vendor_data=user-1234" \ -F "first_name=John" \ -F "last_name=Doe" \ -F "date_of_birth=1990-01-01" \ -F "personal_number=11111111" ``` Every successful call returns HTTP `200`. The **`outcome_code`** field tells you what actually happened — distinguishing, for example, a real biometric mismatch (`BIOMETRIC_NO_MATCH`) from a selfie that could not be read (`BIOMETRIC_IMAGE_UNUSABLE`). The `status` shown is the default feature status; your configured [Partial Match / No Match actions](/core-technology/database-validation/database-validation-warnings) can override it. **`MATCH`** — The registry confirmed the identity and every checked field matched. ```json 200 OK — MATCH theme={null} { "request_id": "req_01H…", "status": "Approved", "issuing_state": "PER", "match_type": "full_match", "validations": [ { "outcome_code": "MATCH", "service_id": "per_tax_registration", "service_name": "Peru Tax Registration (SUNAT)", "source_data": { "date_of_birth": "1990-01-01", "first_name": "John", "full_name": "John Doe", "identification_number": "SAMPLE-ID-12345", "last_name": "Doe", "name_match_score": "1.000", "verifications": { "date_of_birth": true, "full_name": true, "identification_number": true } }, "validation": { "date_of_birth": "full_match", "full_name": "full_match", "identification_number": "full_match" } } ] } ``` **`PARTIAL_MATCH`** — The identification number was found but one or more personal fields (usually name or date of birth) did not fully match. ```json 200 OK — PARTIAL_MATCH theme={null} { "request_id": "req_01H…", "status": "In Review", "issuing_state": "PER", "match_type": "partial_match", "validations": [ { "outcome_code": "PARTIAL_MATCH", "service_id": "per_tax_registration", "service_name": "Peru Tax Registration (SUNAT)", "source_data": { "date_of_birth": "1990-01-01", "first_name": "John", "full_name": "John Doe", "identification_number": "SAMPLE-ID-12345", "last_name": "Doe", "name_match_score": "1.000", "verifications": { "date_of_birth": true, "full_name": false, "identification_number": true } }, "validation": { "date_of_birth": "full_match", "full_name": "no_match", "identification_number": "full_match" } } ] } ``` **`NO_MATCH`** — The registry returned no match for the submitted data. ```json 200 OK — NO_MATCH theme={null} { "request_id": "req_01H…", "status": "Declined", "issuing_state": "PER", "match_type": "no_match", "validations": [ { "outcome_code": "NO_MATCH", "service_id": "per_tax_registration", "service_name": "Peru Tax Registration (SUNAT)", "source_data": { "date_of_birth": "NO_MATCH", "full_name": "NO_MATCH", "identification_number": "NO_MATCH" }, "validation": { "date_of_birth": "no_match", "full_name": "no_match", "identification_number": "no_match" } } ] } ``` ## Returned data The exact fields surfaced in `source_data` depend on what the registry returns. The generated example for `per_tax_registration` currently documents this normalized shape: * `date_of_birth` * `first_name` * `full_name` * `identification_number` * `last_name` * `name_match_score` ## Pricing & SLAs Peru Tax Registration (SUNAT) queries are billed only when Didit receives a conclusive result from the validation source. * **Per-call price:** \$1.75 USD. * **Billing:** per successful query. You are not charged when the registry is unreachable, when required fields are missing, or when the request is rejected before reaching the source. * **Latency:** typical p95 \< 2 s. * **Availability:** 99.9% per quarter on Didit's side; downstream source availability varies by country and dataset. ## Continue reading * [Peru Database Validation overview](/api-reference/database-validation/peru) * [Database Validation overview](/core-technology/database-validation/overview) * [Outcome Codes](/core-technology/database-validation/database-validation-outcome-codes) # Philippines Residential Source: https://docs.didit.me/api-reference/database-validation/philippines/residential POST /v3/database-validation/ Verifies input data against a Government agency database consisting of Filipino citizens data. Authoritative real-time identity lookup for Philippines. Real-time lookup, pay-per-call.
Verifies input data against a Government agency database consisting of Filipino citizens data. Didit exposes this service through `POST /v3/database-validation/` so you can verify the submitted data against the authoritative source and receive normalized match results. ## Coverage * **Coverage:** > 80% * **Country:** Philippines * **Service ID:** `phl_residential` * **Data domain:** Address * **Category:** Residential ## Inputs | Field | Required | Example | | --------------------- | -------: | ------------------- | | `first_name` | Yes | `John` | | `last_name` | Yes | `Doe` | | `date_of_birth` | Yes | `1990-01-01` | | `address.street_1` | No | `123 Sample Street` | | `address.street_2` | No | `Unit 4` | | `address.city` | No | `Sample City` | | `address.region` | No | `Sample State` | | `address.postal_code` | No | `10001` | | `vendor_data` | No | `user-1234` | * **Required inputs:** `first_name`, `last_name`, `date_of_birth` * **Optional inputs:** `address.street_1`, `address.street_2`, `address.city`, `address.region`, `address.postal_code`, `vendor_data` * **Consent:** Required * **Workflow availability:** Available in workflow * **Coverage:** > 80% * **Price:** \$0.35 per successful query ## Body parameters ISO 3166-1 alpha-3 country code for this database service. Example: `PHL` Array containing this service ID. Pinning the service keeps the request scoped to this exact database. Example: `phl_residential` Explicit end-user consent for this service. Example: `true` Given name to validate. Example: `John` Family name to validate. Example: `Doe` Date of birth in `YYYY-MM-DD` format. Example: `1990-01-01` Structured residential address object. Use `street_1`, `street_2`, `city`, `region`, `postal_code`, and `country`. A complete legacy address string is still accepted but not recommended. Example: `{"street_1":"123 Sample Street","street_2":"Unit 4","city":"Sample City","region":"Sample State","postal_code":"10001","country":"US"}` Your stable user reference for this person, such as your internal user ID. Didit uses it to link standalone checks to the same end user and reduce duplicate-detection noise. Example: `user-1234` ## Input rules & validation notes * `address` is optional for this service. You can send one complete `address` string and Didit will split it into structured address elements when possible, or you can send the structured fields explicitly. * For address services, send structured address fields instead of a single `address` string when possible. * `address.street_1` is the street address, including street number and street type. * `address.street_2` is apartment, unit, building, floor, or extra address line. Send it only when you have it. * `address.city` is city, suburb, district, locality, or neighborhood. * `address.region` is state, province, region, or town. * `address.postal_code` is postcode or postal code. * Address-based database services require at least street address and postal code; requests rejected before source lookup are not charged. ## How to call it ```bash cURL theme={null} curl -X POST "https://verification.didit.me/v3/database-validation/" \ -H "x-api-key: YOUR_API_KEY" \ -F "issuing_state=PHL" \ -F "services=phl_residential" \ -F "vendor_data=user-1234" \ -F "consent=true" \ -F "first_name=John" \ -F "last_name=Doe" \ -F "date_of_birth=1990-01-01" ``` Every successful call returns HTTP `200`. The **`outcome_code`** field tells you what actually happened — distinguishing, for example, a real biometric mismatch (`BIOMETRIC_NO_MATCH`) from a selfie that could not be read (`BIOMETRIC_IMAGE_UNUSABLE`). The `status` shown is the default feature status; your configured [Partial Match / No Match actions](/core-technology/database-validation/database-validation-warnings) can override it. **`MATCH`** — The registry confirmed the identity and every checked field matched. ```json 200 OK — MATCH theme={null} { "request_id": "req_01H…", "status": "Approved", "issuing_state": "PHL", "match_type": "full_match", "validations": [ { "outcome_code": "MATCH", "service_id": "phl_residential", "service_name": "Philippines Residential", "source_data": { "date_of_birth": "1990-01-01", "name_match_score": "1.000", "verifications": { "date_of_birth": true, "full_name": true } }, "validation": { "date_of_birth": "full_match", "full_name": "full_match" } } ] } ``` **`PARTIAL_MATCH`** — The identification number was found but one or more personal fields (usually name or date of birth) did not fully match. ```json 200 OK — PARTIAL_MATCH theme={null} { "request_id": "req_01H…", "status": "In Review", "issuing_state": "PHL", "match_type": "partial_match", "validations": [ { "outcome_code": "PARTIAL_MATCH", "service_id": "phl_residential", "service_name": "Philippines Residential", "source_data": { "date_of_birth": "1990-01-01", "name_match_score": "1.000", "verifications": { "date_of_birth": true, "full_name": false } }, "validation": { "date_of_birth": "full_match", "full_name": "no_match" } } ] } ``` **`NO_MATCH`** — The registry returned no match for the submitted data. ```json 200 OK — NO_MATCH theme={null} { "request_id": "req_01H…", "status": "Declined", "issuing_state": "PHL", "match_type": "no_match", "validations": [ { "outcome_code": "NO_MATCH", "service_id": "phl_residential", "service_name": "Philippines Residential", "source_data": { "date_of_birth": "NO_MATCH", "full_name": "NO_MATCH" }, "validation": { "date_of_birth": "no_match", "full_name": "no_match" } } ] } ``` ## Returned data The exact fields surfaced in `source_data` depend on what the registry returns. The generated example for `phl_residential` currently documents this normalized shape: * `date_of_birth` * `name_match_score` ## Pricing & SLAs Philippines Residential queries are billed only when Didit receives a conclusive result from the validation source. * **Per-call price:** \$0.35 USD. * **Billing:** per successful query. You are not charged when the registry is unreachable, when required fields are missing, or when the request is rejected before reaching the source. * **Latency:** typical p95 \< 2 s. * **Availability:** 99.9% per quarter on Didit's side; downstream source availability varies by country and dataset. ## Continue reading * [Philippines Database Validation overview](/api-reference/database-validation/philippines) * [Database Validation overview](/core-technology/database-validation/overview) * [Outcome Codes](/core-technology/database-validation/database-validation-outcome-codes) # Singapore Credit Bureau Source: https://docs.didit.me/api-reference/database-validation/singapore/credit-bureau POST /v3/database-validation/ Verifies input data against Credit Header data obtained from a Credit Bureau in Singapore. Authoritative real-time identity lookup for Singapore. Real-time lookup, pay-per-call.
Verifies input data against Credit Header data obtained from a Credit Bureau in Singapore. Didit exposes this service through `POST /v3/database-validation/` so you can verify the submitted data against the authoritative source and receive normalized match results. ## Coverage * **Coverage:** undisclosed * **Country:** Singapore * **Service ID:** `sgp_credit_bureau` * **Data domain:** Financial * **Category:** CreditBureau ## Inputs | Field | Required | Example | | --------------------- | -------: | ------------------- | | `full_name` | Yes | `John Doe` | | `date_of_birth` | Yes | `1990-01-01` | | `address.street_1` | Yes | `123 Sample Street` | | `address.postal_code` | Yes | `10001` | | `national_id` | Yes | `SAMPLE-NID-12345` | | `address.street_2` | No | `Unit 4` | | `address.city` | No | `Sample City` | | `address.region` | No | `Sample State` | | `vendor_data` | No | `user-1234` | * **Required inputs:** `full_name`, `date_of_birth`, `address.street_1`, `address.postal_code`, `national_id` * **Optional inputs:** `address.street_2`, `address.city`, `address.region`, `vendor_data` * **Consent:** Required * **Workflow availability:** Available in workflow * **Coverage:** undisclosed * **Price:** \$2.61 per successful query ## Body parameters ISO 3166-1 alpha-3 country code for this database service. Example: `SGP` Array containing this service ID. Pinning the service keeps the request scoped to this exact database. Example: `sgp_credit_bureau` Explicit end-user consent for this service. Example: `true` Full legal name to validate. Example: `John Doe` Date of birth in `YYYY-MM-DD` format. Example: `1990-01-01` Structured residential address object. Use `street_1`, `street_2`, `city`, `region`, `postal_code`, and `country`. A complete legacy address string is still accepted but not recommended. Example: `{"street_1":"123 Sample Street","street_2":"Unit 4","city":"Sample City","region":"Sample State","postal_code":"10001","country":"US"}` National identity number for this service. Example: `SAMPLE-NID-12345` Your stable user reference for this person, such as your internal user ID. Didit uses it to link standalone checks to the same end user and reduce duplicate-detection noise. Example: `user-1234` ## Input rules & validation notes * For address services, send structured address fields instead of a single `address` string when possible. * `address.street_1` is the street address, including street number and street type. * `address.street_2` is apartment, unit, building, floor, or extra address line. Send it only when you have it. * `address.city` is city, suburb, district, locality, or neighborhood. * `address.region` is state, province, region, or town. * `address.postal_code` is postcode or postal code. * Address-based database services require at least street address and postal code; requests rejected before source lookup are not charged. ## How to call it ```bash cURL theme={null} curl -X POST "https://verification.didit.me/v3/database-validation/" \ -H "x-api-key: YOUR_API_KEY" \ -F "issuing_state=SGP" \ -F "services=sgp_credit_bureau" \ -F "vendor_data=user-1234" \ -F "consent=true" \ -F "full_name=John Doe" \ -F "date_of_birth=1990-01-01" \ -F 'address={"street_1":"123 Sample Street","street_2":"Unit 4","city":"Sample City","region":"Sample State","postal_code":"10001","country":"US"}' \ -F "national_id=SAMPLE-NID-12345" ``` Every successful call returns HTTP `200`. The **`outcome_code`** field tells you what actually happened — distinguishing, for example, a real biometric mismatch (`BIOMETRIC_NO_MATCH`) from a selfie that could not be read (`BIOMETRIC_IMAGE_UNUSABLE`). The `status` shown is the default feature status; your configured [Partial Match / No Match actions](/core-technology/database-validation/database-validation-warnings) can override it. **`MATCH`** — The registry confirmed the identity and every checked field matched. ```json 200 OK — MATCH theme={null} { "request_id": "req_01H…", "status": "Approved", "issuing_state": "SGP", "match_type": "full_match", "validations": [ { "outcome_code": "MATCH", "service_id": "sgp_credit_bureau", "service_name": "Singapore Credit Bureau", "source_data": { "address": "123 Sample Street", "address_match_score": "1.000", "city": "Sample City", "date_of_birth": "1990-01-01", "identification_number": "SAMPLE-ID-12345", "postal_code": "10001", "street": "sample_value", "verifications": { "address": true, "date_of_birth": true, "full_name": true, "identification_number": true } }, "validation": { "address": "full_match", "date_of_birth": "full_match", "full_name": "full_match", "identification_number": "full_match" } } ] } ``` **`PARTIAL_MATCH`** — The identification number was found but one or more personal fields (usually name or date of birth) did not fully match. ```json 200 OK — PARTIAL_MATCH theme={null} { "request_id": "req_01H…", "status": "In Review", "issuing_state": "SGP", "match_type": "partial_match", "validations": [ { "outcome_code": "PARTIAL_MATCH", "service_id": "sgp_credit_bureau", "service_name": "Singapore Credit Bureau", "source_data": { "address": "123 Sample Street", "address_match_score": "1.000", "city": "Sample City", "date_of_birth": "1990-01-01", "identification_number": "SAMPLE-ID-12345", "postal_code": "10001", "street": "sample_value", "verifications": { "address": true, "date_of_birth": true, "full_name": false, "identification_number": true } }, "validation": { "address": "full_match", "date_of_birth": "full_match", "full_name": "no_match", "identification_number": "full_match" } } ] } ``` **`NO_MATCH`** — The registry returned no match for the submitted data. ```json 200 OK — NO_MATCH theme={null} { "request_id": "req_01H…", "status": "Declined", "issuing_state": "SGP", "match_type": "no_match", "validations": [ { "outcome_code": "NO_MATCH", "service_id": "sgp_credit_bureau", "service_name": "Singapore Credit Bureau", "source_data": { "address": "NO_MATCH", "date_of_birth": "NO_MATCH", "full_name": "NO_MATCH", "identification_number": "NO_MATCH" }, "validation": { "address": "no_match", "date_of_birth": "no_match", "full_name": "no_match", "identification_number": "no_match" } } ] } ``` ## Returned data The exact fields surfaced in `source_data` depend on what the registry returns. The generated example for `sgp_credit_bureau` currently documents this normalized shape: * `address` * `address_match_score` * `city` * `date_of_birth` * `identification_number` * `postal_code` * `street` ## Pricing & SLAs Singapore Credit Bureau queries are billed only when Didit receives a conclusive result from the validation source. * **Per-call price:** \$2.61 USD. * **Billing:** per successful query. You are not charged when the registry is unreachable, when required fields are missing, or when the request is rejected before reaching the source. * **Latency:** typical p95 \< 2 s. * **Availability:** 99.9% per quarter on Didit's side; downstream source availability varies by country and dataset. ## Continue reading * [Singapore Database Validation overview](/api-reference/database-validation/singapore) * [Database Validation overview](/core-technology/database-validation/overview) * [Outcome Codes](/core-technology/database-validation/database-validation-outcome-codes) # Singapore Utility Source: https://docs.didit.me/api-reference/database-validation/singapore/utility POST /v3/database-validation/ Verifies input data to telco billing records and phone data. Authoritative real-time identity lookup for Singapore. Real-time lookup, pay-per-call.
Verifies input data to telco billing records and phone data. Didit exposes this service through `POST /v3/database-validation/` so you can verify the submitted data against the authoritative source and receive normalized match results. ## Coverage * **Coverage:** > 80% * **Country:** Singapore * **Service ID:** `sgp_utility` * **Data domain:** Address * **Category:** Utility ## Inputs | Field | Required | Example | | --------------------- | -------: | ------------------- | | `first_name` | Yes | `John` | | `last_name` | Yes | `Doe` | | `address.street_1` | Yes | `123 Sample Street` | | `address.postal_code` | Yes | `10001` | | `date_of_birth` | No | `1990-01-01` | | `phone` | No | `+15550101000` | | `address.street_2` | No | `Unit 4` | | `address.city` | No | `Sample City` | | `address.region` | No | `Sample State` | | `vendor_data` | No | `user-1234` | * **Required inputs:** `first_name`, `last_name`, `address.street_1`, `address.postal_code` * **Optional inputs:** `date_of_birth`, `phone`, `address.street_2`, `address.city`, `address.region`, `vendor_data` * **Consent:** Not required * **Workflow availability:** Available in workflow * **Coverage:** > 80% * **Price:** \$1.69 per successful query ## Body parameters ISO 3166-1 alpha-3 country code for this database service. Example: `SGP` Array containing this service ID. Pinning the service keeps the request scoped to this exact database. Example: `sgp_utility` Given name to validate. Example: `John` Family name to validate. Example: `Doe` Structured residential address object. Use `street_1`, `street_2`, `city`, `region`, `postal_code`, and `country`. A complete legacy address string is still accepted but not recommended. Example: `{"street_1":"123 Sample Street","street_2":"Unit 4","city":"Sample City","region":"Sample State","postal_code":"10001","country":"US"}` Date of birth in `YYYY-MM-DD` format. Example: `1990-01-01` Phone number in international format. Example: `+15550101000` Your stable user reference for this person, such as your internal user ID. Didit uses it to link standalone checks to the same end user and reduce duplicate-detection noise. Example: `user-1234` ## Input rules & validation notes * For address services, send structured address fields instead of a single `address` string when possible. * `address.street_1` is the street address, including street number and street type. * `address.street_2` is apartment, unit, building, floor, or extra address line. Send it only when you have it. * `address.city` is city, suburb, district, locality, or neighborhood. * `address.region` is state, province, region, or town. * `address.postal_code` is postcode or postal code. * Address-based database services require at least street address and postal code; requests rejected before source lookup are not charged. ## How to call it ```bash cURL theme={null} curl -X POST "https://verification.didit.me/v3/database-validation/" \ -H "x-api-key: YOUR_API_KEY" \ -F "issuing_state=SGP" \ -F "services=sgp_utility" \ -F "vendor_data=user-1234" \ -F "first_name=John" \ -F "last_name=Doe" \ -F 'address={"street_1":"123 Sample Street","street_2":"Unit 4","city":"Sample City","region":"Sample State","postal_code":"10001","country":"US"}' ``` Every successful call returns HTTP `200`. The **`outcome_code`** field tells you what actually happened — distinguishing, for example, a real biometric mismatch (`BIOMETRIC_NO_MATCH`) from a selfie that could not be read (`BIOMETRIC_IMAGE_UNUSABLE`). The `status` shown is the default feature status; your configured [Partial Match / No Match actions](/core-technology/database-validation/database-validation-warnings) can override it. **`MATCH`** — The registry confirmed the identity and every checked field matched. ```json 200 OK — MATCH theme={null} { "request_id": "req_01H…", "status": "Approved", "issuing_state": "SGP", "match_type": "full_match", "validations": [ { "outcome_code": "MATCH", "service_id": "sgp_utility", "service_name": "Singapore Utility", "source_data": { "address": "123 Sample Street", "address_match_score": "1.000", "city": "Sample City", "date_of_birth": "1990-01-01", "first_name": "John", "full_name": "John Doe", "last_name": "Doe", "name_match_score": "1.000", "postal_code": "10001", "street": "sample_value", "verifications": { "address": true, "full_name": true } }, "validation": { "address": "full_match", "full_name": "full_match" } } ] } ``` **`PARTIAL_MATCH`** — The identification number was found but one or more personal fields (usually name or date of birth) did not fully match. ```json 200 OK — PARTIAL_MATCH theme={null} { "request_id": "req_01H…", "status": "In Review", "issuing_state": "SGP", "match_type": "partial_match", "validations": [ { "outcome_code": "PARTIAL_MATCH", "service_id": "sgp_utility", "service_name": "Singapore Utility", "source_data": { "address": "123 Sample Street", "address_match_score": "1.000", "city": "Sample City", "date_of_birth": "1990-01-01", "first_name": "John", "full_name": "John Doe", "last_name": "Doe", "name_match_score": "1.000", "postal_code": "10001", "street": "sample_value", "verifications": { "address": true, "full_name": false } }, "validation": { "address": "full_match", "full_name": "no_match" } } ] } ``` **`NO_MATCH`** — The registry returned no match for the submitted data. ```json 200 OK — NO_MATCH theme={null} { "request_id": "req_01H…", "status": "Declined", "issuing_state": "SGP", "match_type": "no_match", "validations": [ { "outcome_code": "NO_MATCH", "service_id": "sgp_utility", "service_name": "Singapore Utility", "source_data": { "address": "NO_MATCH", "full_name": "NO_MATCH" }, "validation": { "address": "no_match", "full_name": "no_match" } } ] } ``` ## Returned data The exact fields surfaced in `source_data` depend on what the registry returns. The generated example for `sgp_utility` currently documents this normalized shape: * `address` * `address_match_score` * `city` * `date_of_birth` * `first_name` * `full_name` * `last_name` * `name_match_score` * `postal_code` * `street` ## Pricing & SLAs Singapore Utility queries are billed only when Didit receives a conclusive result from the validation source. * **Per-call price:** \$1.69 USD. * **Billing:** per successful query. You are not charged when the registry is unreachable, when required fields are missing, or when the request is rejected before reaching the source. * **Latency:** typical p95 \< 2 s. * **Availability:** 99.9% per quarter on Didit's side; downstream source availability varies by country and dataset. ## Continue reading * [Singapore Database Validation overview](/api-reference/database-validation/singapore) * [Database Validation overview](/core-technology/database-validation/overview) * [Outcome Codes](/core-technology/database-validation/database-validation-outcome-codes) # South Africa - Bank Account Holder Verification Source: https://docs.didit.me/api-reference/database-validation/south-africa/bank-account-holder POST /v3/database-validation/ Confirms a South African bank account belongs to the named holder via the inter-bank Account Holder Verification service. Authoritative real-time identity lookup for South Africa. Real-time lookup, pay-per-call.
Confirms a South African bank account belongs to the named holder via the inter-bank Account Holder Verification service. Didit exposes this service through `POST /v3/database-validation/` so you can verify the submitted data against the authoritative source and receive normalized match results. ## Coverage * **Coverage:** — * **Country:** South Africa * **Service ID:** `zaf_bank_account_holder` * **Data domain:** Financial * **Category:** Banking ## Inputs | Field | Required | Example | | --------------------- | -------: | ---------------------- | | `national_id` | Yes | `8708150847085` | | `bank_account_number` | Yes | `1234567890` | | `bank_name` | Yes | `ABSA` | | `account_type` | No | `current` | | `first_name` | No | `John` | | `last_name` | No | `Doe` | | `initials` | No | `JD` | | `email` | No | `john.doe@example.com` | | `phone_number` | No | `+15550101000` | | `vendor_data` | No | `user-1234` | * **Required inputs:** `national_id`, `bank_account_number`, `bank_name` * **Optional inputs:** `account_type`, `first_name`, `last_name`, `initials`, `email`, `phone_number`, `vendor_data` * **Consent:** Required * **Workflow availability:** Available in workflow with field mapping * **Coverage:** — * **Price:** \$0.40 per successful query In a workflow, `bank_account_number` and `bank_name` are not printed on an identity document, so no step produces them on their own. Collect them from a Questionnaire answer, a Document AI extraction field, or a value you send when you create the session, and map each one on the Database Validation step. Until they are mapped the workflow editor shows this service disabled and names the missing input; at run time a missing input means the check is skipped before any query, so you are never billed for a database that could not be asked. ## Body parameters ISO 3166-1 alpha-3 country code for this database service. Example: `ZAF` Array containing this service ID. Pinning the service keeps the request scoped to this exact database. Example: `zaf_bank_account_holder` Explicit end-user consent for this service. Example: `true` National identity number for this service. Example: `8708150847085` `bank_account_number` value required by this database service. Example: `1234567890` `bank_name` value required by this database service. Example: `ABSA` `account_type` value required by this database service. Example: `current` Given name to validate. Example: `John` Family name to validate. Example: `Doe` `initials` value required by this database service. Example: `JD` Email address. Example: `john.doe@example.com` `phone_number` value required by this database service. Example: `+15550101000` Your stable user reference for this person, such as your internal user ID. Didit uses it to link standalone checks to the same end user and reduce duplicate-detection noise. Example: `user-1234` ## Input rules & validation notes * `account_type` must be one of the South African AVS account types: `current`, `savings`, `transmission`, `subscriptionShare`, `notKnown`. Matching is case-insensitive. Omit the field when you do not know the account type - Didit then sends `notKnown` and the account-type cross-check is reported as not confirmed instead of failing the request. ## How to call it ```bash cURL theme={null} curl -X POST "https://verification.didit.me/v3/database-validation/" \ -H "x-api-key: YOUR_API_KEY" \ -F "issuing_state=ZAF" \ -F "services=zaf_bank_account_holder" \ -F "vendor_data=user-1234" \ -F "consent=true" \ -F "national_id=8708150847085" \ -F "bank_account_number=1234567890" \ -F "bank_name=ABSA" \ -F "account_type=current" \ -F "last_name=Doe" \ -F "initials=JD" ``` Every successful call returns HTTP `200`. The **`outcome_code`** field tells you what actually happened — distinguishing, for example, a real biometric mismatch (`BIOMETRIC_NO_MATCH`) from a selfie that could not be read (`BIOMETRIC_IMAGE_UNUSABLE`). The `status` shown is the default feature status; your configured [Partial Match / No Match actions](/core-technology/database-validation/database-validation-warnings) can override it. **`MATCH`** — The registry confirmed the identity and every checked field matched. ```json 200 OK — MATCH theme={null} { "request_id": "req_01H…", "status": "Approved", "issuing_state": "ZAF", "match_type": "full_match", "validations": [ { "outcome_code": "MATCH", "service_id": "zaf_bank_account_holder", "service_name": "South Africa - Bank Account Holder Verification", "source_data": { "accepts_credits": true, "accepts_debits": true, "account_found": true, "account_number_length_valid": true, "account_open": true, "account_type_match": true, "id_match": true, "identification_number": "SAMPLE-ID-12345", "initials_match": true, "surname_match": true }, "validation": { "full_name": "full_match", "identification_number": "full_match" } } ] } ``` **`PARTIAL_MATCH`** — The identification number was found but one or more personal fields (usually name or date of birth) did not fully match. ```json 200 OK — PARTIAL_MATCH theme={null} { "request_id": "req_01H…", "status": "In Review", "issuing_state": "ZAF", "match_type": "partial_match", "validations": [ { "outcome_code": "PARTIAL_MATCH", "service_id": "zaf_bank_account_holder", "service_name": "South Africa - Bank Account Holder Verification", "source_data": { "accepts_credits": true, "accepts_debits": true, "account_found": true, "account_number_length_valid": false, "account_open": true, "account_type_match": true, "id_match": true, "identification_number": "SAMPLE-ID-12345", "initials_match": true, "surname_match": false }, "validation": { "full_name": "partial_match", "identification_number": "full_match" } } ] } ``` **`NO_MATCH`** — The registry returned no match for the submitted data. ```json 200 OK — NO_MATCH theme={null} { "request_id": "req_01H…", "status": "Declined", "issuing_state": "ZAF", "match_type": "no_match", "validations": [ { "outcome_code": "NO_MATCH", "service_id": "zaf_bank_account_holder", "service_name": "South Africa - Bank Account Holder Verification", "source_data": { "accepts_credits": false, "accepts_debits": false, "account_found": false, "account_number_length_valid": false, "account_open": false, "account_type_match": false, "id_match": false, "identification_number": "NO_MATCH", "initials_match": false, "surname_match": false }, "validation": { "identification_number": "no_match" } } ] } ``` ## Returned data The exact fields surfaced in `source_data` depend on what the registry returns. The generated example for `zaf_bank_account_holder` currently documents this normalized shape: * `accepts_credits` * `accepts_debits` * `account_found` * `account_number_length_valid` * `account_open` * `account_type_match` * `id_match` * `identification_number` * `initials_match` * `surname_match` ## Pricing & SLAs South Africa - Bank Account Holder Verification queries are billed only when Didit receives a conclusive result from the validation source. * **Per-call price:** \$0.40 USD. * **Billing:** per successful query. You are not charged when the registry is unreachable, when required fields are missing, or when the request is rejected before reaching the source. * **Latency:** typical p95 \< 2 s. * **Availability:** 99.9% per quarter on Didit's side; downstream source availability varies by country and dataset. ## What a MATCH confirms Account Holder Verification (AVS) is a set of yes/no cross-checks, not a record lookup. The source never returns a name, an ID number or an account balance - it takes the details you send, compares them against what the bank holds for that account, and answers each comparison with a flag. `source_data` carries those flags: * **`account_found`** - the bank holds an account with this number. Everything else is meaningless when this is `false`. * **`account_open`** - the account is open. An account can be found but closed. * **`id_match`** - the account is held by the national id you submitted. This is the check the service exists for. * **`initials_match`**, **`surname_match`** - the submitted `initials` and `last_name` match the account holder on file. * **`account_type_match`** - the submitted `account_type` matches the account's real type. * **`email_match`**, **`phone_match`** - the submitted `email` and `phone_number` match the contact details the bank holds. * **`accepts_debits`**, **`accepts_credits`** - the account can receive debit orders and credits. * **`account_number_length_valid`** - the account number is the length the bank expects. The outcome code summarises them: * **`MATCH`** - the account exists and every field you submitted matched, `id_match` included. * **`PARTIAL_MATCH`** - the account is held by the submitted national id, but at least one other field you sent did not match (a surname spelled differently on the bank's records, for example). `outcome_detail` names the fields that failed. * **`NO_MATCH`** - either the bank holds no such account, or the account exists but belongs to someone else. Both are conclusive answers about the person. A cross-check you did not ask for is neither counted nor reported. AVS answers `N` for every field that was not supplied, so `surname_match`, `initials_match`, `email_match`, `phone_match` and `account_type_match` appear in `source_data` only when you sent the matching input. Sending only `national_id`, `bank_account_number` and `bank_name` therefore still produces a full `MATCH`. ## Accepted bank\_name and account\_type values `bank_name` and `account_type` are enumerations. A value outside either list is refused before the query runs, so a typo costs you a round-trip rather than a charge. `account_type` is optional and accepts, case-insensitively: `current` · `savings` · `transmission` · `subscriptionShare` · `notKnown` Omit it when you do not know the account type. Didit then sends `notKnown`, the request succeeds, and `account_type_match` comes back `false` because there was nothing to compare. Any other value - `checking`, `cheque`, `bond` - is rejected with a `400` that lists the accepted set. `bank_name` is required, and these values are confirmed accepted (case-insensitive): `ABSA` · `Capitec` · `FNB` · `Nedbank` · `Standard Bank` · `Investec` · `African Bank` · `Discovery Bank` · `Old Mutual` · `Bank Zero` · `Tyme` · `Grindrod` Consumer accounts at all of these are in scope, Capitec included. Send the short form exactly as listed - `Capitec`, not `Capitec Bank`; `Tyme`, not `TymeBank`. An unrecognised bank comes back as an outcome of `REGISTRY_ERROR` whose `outcome_detail` names the field the source refused. ## Telling a missing account apart from an unavailable source These are different HTTP outcomes, so no parsing of error strings is needed: * **The account does not exist** - `200 OK`, `match_type: "no_match"`, `outcome_code: "NO_MATCH"`, `source_data.account_found: false`. A real answer from the bank. Billed, and your no-match action applies. * **The source did not answer** - `502 Bad Gateway` with `validation_errors[].code` = `empty_provider_response` and `retryable: true`. Nothing was established about the person, nothing is billed, and the request is safe to retry. * **The source refused to run the query** - `400 Bad Request` with `validation_errors[].code` = `provider_rejected_input` and `retryable: false`. The source never searched, because it would not accept what it was sent. Correct the data; retrying the same values cannot succeed. Nothing is billed. * **The source answered and rejected your input** - `502 Bad Gateway` with `validation_errors[].code` = `provider_invalid_input` (for example an account number that fails the bank's own format check). Retrying is pointless until the input is corrected; nothing is billed. * **Your request never left Didit** - `400 Bad Request`, listing the field to fix. Nothing is billed. Only the first of these is an answer about the person. Treat a `502` as transient - AVS relays to the account holder's bank rather than reading a registry, so it is the slowest of the South African services - and retry with backoff. ## Continue reading * [South Africa Database Validation overview](/api-reference/database-validation/south-africa) * [Database Validation overview](/core-technology/database-validation/overview) * [Outcome Codes](/core-technology/database-validation/database-validation-outcome-codes) # South Africa - Company Directors Lookup Source: https://docs.didit.me/api-reference/database-validation/south-africa/company-directors POST /v3/database-validation/ Returns the current directors of a South African company from the CIPC commercial register. Authoritative real-time identity lookup for South Africa. Real-time lookup, pay-per-call.
Returns the current directors of a South African company from the CIPC commercial register. Didit exposes this service through `POST /v3/database-validation/` so you can verify the submitted data against the authoritative source and receive normalized match results. ## Coverage * **Coverage:** — * **Country:** South Africa * **Service ID:** `zaf_company_directors` * **Data domain:** Government * **Category:** CompanyRegister ## Inputs | Field | Required | Example | | ----------------------------- | -------: | ------------ | | `company_registration_number` | Yes | `REG-123456` | | `vendor_data` | No | `user-1234` | * **Required inputs:** `company_registration_number` * **Optional inputs:** `vendor_data` * **Consent:** Not required * **Workflow availability:** Available in workflow with field mapping * **Coverage:** — * **Price:** \$0.65 per successful query In a workflow, `company_registration_number` is not printed on an identity document, so no step produces it on its own. Collect it from a Questionnaire answer, a Document AI extraction field, or a value you send when you create the session, and map it on the Database Validation step. Until it is mapped the workflow editor shows this service disabled and names the missing input; at run time a missing input means the check is skipped before any query, so you are never billed for a database that could not be asked. ## Body parameters ISO 3166-1 alpha-3 country code for this database service. Example: `ZAF` Array containing this service ID. Pinning the service keeps the request scoped to this exact database. Example: `zaf_company_directors` `company_registration_number` value required by this database service. Example: `REG-123456` Your stable user reference for this person, such as your internal user ID. Didit uses it to link standalone checks to the same end user and reduce duplicate-detection noise. Example: `user-1234` ## Input rules & validation notes * Send the fields listed above exactly as captured from the user or document. * Didit validates required fields before calling the database. Requests rejected before source lookup are not charged. ## How to call it ```bash cURL theme={null} curl -X POST "https://verification.didit.me/v3/database-validation/" \ -H "x-api-key: YOUR_API_KEY" \ -F "issuing_state=ZAF" \ -F "services=zaf_company_directors" \ -F "vendor_data=user-1234" \ -F "company_registration_number=REG-123456" ``` Every successful call returns HTTP `200`. The **`outcome_code`** field tells you what actually happened — distinguishing, for example, a real biometric mismatch (`BIOMETRIC_NO_MATCH`) from a selfie that could not be read (`BIOMETRIC_IMAGE_UNUSABLE`). The `status` shown is the default feature status; your configured [Partial Match / No Match actions](/core-technology/database-validation/database-validation-warnings) can override it. **`MATCH`** — The registry confirmed the identity and every checked field matched. ```json 200 OK — MATCH theme={null} { "request_id": "req_01H…", "status": "Approved", "issuing_state": "ZAF", "match_type": "full_match", "validations": [ { "outcome_code": "MATCH", "service_id": "zaf_company_directors", "service_name": "South Africa - Company Directors Lookup", "source_data": {}, "validation": { "identification_number": "full_match" } } ] } ``` **`NO_MATCH`** — The registry returned no match for the submitted data. ```json 200 OK — NO_MATCH theme={null} { "request_id": "req_01H…", "status": "Declined", "issuing_state": "ZAF", "match_type": "no_match", "validations": [ { "outcome_code": "NO_MATCH", "service_id": "zaf_company_directors", "service_name": "South Africa - Company Directors Lookup", "source_data": { "identification_number": "NO_MATCH" }, "validation": { "identification_number": "no_match" } } ] } ``` ## Returned data The exact fields surfaced in `source_data` depend on what the registry returns. The generated example for `zaf_company_directors` currently documents this normalized shape: * Varies by registry response. ## Pricing & SLAs South Africa - Company Directors Lookup queries are billed only when Didit receives a conclusive result from the validation source. * **Per-call price:** \$0.65 USD. * **Billing:** per successful query. You are not charged when the registry is unreachable, when required fields are missing, or when the request is rejected before reaching the source. * **Latency:** typical p95 \< 2 s. * **Availability:** 99.9% per quarter on Didit's side; downstream source availability varies by country and dataset. ## Continue reading * [South Africa Database Validation overview](/api-reference/database-validation/south-africa) * [Database Validation overview](/core-technology/database-validation/overview) * [Outcome Codes](/core-technology/database-validation/database-validation-outcome-codes) # South Africa - Company Registry Lookup Source: https://docs.didit.me/api-reference/database-validation/south-africa/company-registry POST /v3/database-validation/ Looks up a South African company by registration number against the CIPC commercial register. Authoritative real-time identity lookup for South Africa. Real-time lookup, pay-per-call.
Looks up a South African company by registration number against the CIPC commercial register. Didit exposes this service through `POST /v3/database-validation/` so you can verify the submitted data against the authoritative source and receive normalized match results. ## Coverage * **Coverage:** — * **Country:** South Africa * **Service ID:** `zaf_company_registry` * **Data domain:** Government * **Category:** CompanyRegister ## Inputs | Field | Required | Example | | ----------------------------- | -------: | -------------------- | | `company_registration_number` | Yes | `REG-123456` | | `company_name` | No | `Sample Company LLC` | | `vendor_data` | No | `user-1234` | * **Required inputs:** `company_registration_number` * **Optional inputs:** `company_name`, `vendor_data` * **Consent:** Not required * **Workflow availability:** Available in workflow with field mapping * **Coverage:** — * **Price:** \$0.65 per successful query In a workflow, `company_registration_number` is not printed on an identity document, so no step produces it on its own. Collect it from a Questionnaire answer, a Document AI extraction field, or a value you send when you create the session, and map it on the Database Validation step. Until it is mapped the workflow editor shows this service disabled and names the missing input; at run time a missing input means the check is skipped before any query, so you are never billed for a database that could not be asked. ## Body parameters ISO 3166-1 alpha-3 country code for this database service. Example: `ZAF` Array containing this service ID. Pinning the service keeps the request scoped to this exact database. Example: `zaf_company_registry` `company_registration_number` value required by this database service. Example: `REG-123456` `company_name` value required by this database service. Example: `Sample Company LLC` Your stable user reference for this person, such as your internal user ID. Didit uses it to link standalone checks to the same end user and reduce duplicate-detection noise. Example: `user-1234` ## Input rules & validation notes * Send the fields listed above exactly as captured from the user or document. * Didit validates required fields before calling the database. Requests rejected before source lookup are not charged. ## How to call it ```bash cURL theme={null} curl -X POST "https://verification.didit.me/v3/database-validation/" \ -H "x-api-key: YOUR_API_KEY" \ -F "issuing_state=ZAF" \ -F "services=zaf_company_registry" \ -F "vendor_data=user-1234" \ -F "company_registration_number=REG-123456" ``` Every successful call returns HTTP `200`. The **`outcome_code`** field tells you what actually happened — distinguishing, for example, a real biometric mismatch (`BIOMETRIC_NO_MATCH`) from a selfie that could not be read (`BIOMETRIC_IMAGE_UNUSABLE`). The `status` shown is the default feature status; your configured [Partial Match / No Match actions](/core-technology/database-validation/database-validation-warnings) can override it. **`MATCH`** — The registry confirmed the identity and every checked field matched. ```json 200 OK — MATCH theme={null} { "request_id": "req_01H…", "status": "Approved", "issuing_state": "ZAF", "match_type": "full_match", "validations": [ { "outcome_code": "MATCH", "service_id": "zaf_company_registry", "service_name": "South Africa - Company Registry Lookup", "source_data": {}, "validation": { "identification_number": "full_match" } } ] } ``` **`NO_MATCH`** — The registry returned no match for the submitted data. ```json 200 OK — NO_MATCH theme={null} { "request_id": "req_01H…", "status": "Declined", "issuing_state": "ZAF", "match_type": "no_match", "validations": [ { "outcome_code": "NO_MATCH", "service_id": "zaf_company_registry", "service_name": "South Africa - Company Registry Lookup", "source_data": { "identification_number": "NO_MATCH" }, "validation": { "identification_number": "no_match" } } ] } ``` ## Returned data The exact fields surfaced in `source_data` depend on what the registry returns. The generated example for `zaf_company_registry` currently documents this normalized shape: * Varies by registry response. ## Pricing & SLAs South Africa - Company Registry Lookup queries are billed only when Didit receives a conclusive result from the validation source. * **Per-call price:** \$0.65 USD. * **Billing:** per successful query. You are not charged when the registry is unreachable, when required fields are missing, or when the request is rejected before reaching the source. * **Latency:** typical p95 \< 2 s. * **Availability:** 99.9% per quarter on Didit's side; downstream source availability varies by country and dataset. ## Continue reading * [South Africa Database Validation overview](/api-reference/database-validation/south-africa) * [Database Validation overview](/core-technology/database-validation/overview) * [Outcome Codes](/core-technology/database-validation/database-validation-outcome-codes) # South Africa - Contactability Lookup Source: https://docs.didit.me/api-reference/database-validation/south-africa/contactability POST /v3/database-validation/ Returns known phone numbers, emails, and addresses tied to a South African individual. Authoritative real-time identity lookup for South Africa. Real-time lookup, pay-per-call.
Returns known phone numbers, emails, and addresses tied to a South African individual. Didit exposes this service through `POST /v3/database-validation/` so you can verify the submitted data against the authoritative source and receive normalized match results. ## Coverage * **Coverage:** — * **Country:** South Africa * **Service ID:** `zaf_contactability` * **Data domain:** Telecom * **Category:** Telecom ## Inputs | Field | Required | Example | | ------------- | -------: | ------------------ | | `national_id` | Yes | `SAMPLE-NID-12345` | | `vendor_data` | No | `user-1234` | * **Required inputs:** `national_id` * **Optional inputs:** `vendor_data` * **Consent:** Required * **Workflow availability:** Available in workflow * **Coverage:** — * **Price:** \$0.35 per successful query ## Body parameters ISO 3166-1 alpha-3 country code for this database service. Example: `ZAF` Array containing this service ID. Pinning the service keeps the request scoped to this exact database. Example: `zaf_contactability` Explicit end-user consent for this service. Example: `true` National identity number for this service. Example: `SAMPLE-NID-12345` Your stable user reference for this person, such as your internal user ID. Didit uses it to link standalone checks to the same end user and reduce duplicate-detection noise. Example: `user-1234` ## Input rules & validation notes * Send the fields listed above exactly as captured from the user or document. * Didit validates required fields before calling the database. Requests rejected before source lookup are not charged. ## How to call it ```bash cURL theme={null} curl -X POST "https://verification.didit.me/v3/database-validation/" \ -H "x-api-key: YOUR_API_KEY" \ -F "issuing_state=ZAF" \ -F "services=zaf_contactability" \ -F "vendor_data=user-1234" \ -F "consent=true" \ -F "national_id=SAMPLE-NID-12345" ``` Every successful call returns HTTP `200`. The **`outcome_code`** field tells you what actually happened — distinguishing, for example, a real biometric mismatch (`BIOMETRIC_NO_MATCH`) from a selfie that could not be read (`BIOMETRIC_IMAGE_UNUSABLE`). The `status` shown is the default feature status; your configured [Partial Match / No Match actions](/core-technology/database-validation/database-validation-warnings) can override it. **`MATCH`** — The registry confirmed the identity and every checked field matched. ```json 200 OK — MATCH theme={null} { "request_id": "req_01H…", "status": "Approved", "issuing_state": "ZAF", "match_type": "full_match", "validations": [ { "outcome_code": "MATCH", "service_id": "zaf_contactability", "service_name": "South Africa - Contactability Lookup", "source_data": { "contact_email": "alex.sample@example.com", "contact_phone_numbers": "+15550101000", "date_of_birth": "1990-01-01", "deceased": "sample_value", "first_name": "John", "gender": "M", "identification_number": "SAMPLE-ID-12345", "last_name": "Doe", "phone_history_count": "+15550101000" }, "validation": { "identification_number": "full_match" } } ] } ``` **`NO_MATCH`** — The registry returned no match for the submitted data. ```json 200 OK — NO_MATCH theme={null} { "request_id": "req_01H…", "status": "Declined", "issuing_state": "ZAF", "match_type": "no_match", "validations": [ { "outcome_code": "NO_MATCH", "service_id": "zaf_contactability", "service_name": "South Africa - Contactability Lookup", "source_data": { "identification_number": "NO_MATCH" }, "validation": { "identification_number": "no_match" } } ] } ``` ## Returned data The exact fields surfaced in `source_data` depend on what the registry returns. The generated example for `zaf_contactability` currently documents this normalized shape: * `contact_email` * `contact_phone_numbers` * `date_of_birth` * `deceased` * `first_name` * `gender` * `identification_number` * `last_name` * `phone_history_count` ## Pricing & SLAs South Africa - Contactability Lookup queries are billed only when Didit receives a conclusive result from the validation source. * **Per-call price:** \$0.35 USD. * **Billing:** per successful query. You are not charged when the registry is unreachable, when required fields are missing, or when the request is rejected before reaching the source. * **Latency:** typical p95 \< 2 s. * **Availability:** 99.9% per quarter on Didit's side; downstream source availability varies by country and dataset. ## Continue reading * [South Africa Database Validation overview](/api-reference/database-validation/south-africa) * [Database Validation overview](/core-technology/database-validation/overview) * [Outcome Codes](/core-technology/database-validation/database-validation-outcome-codes) # South Africa - Criminal Screening by Face Source: https://docs.didit.me/api-reference/database-validation/south-africa/criminal-face-screening POST /v3/database-validation/ Screens a facial image against published criminal-record datasets to surface potential matches. Authoritative real-time identity lookup for South Africa. Real-time lookup, pay-per-call.
Screens a facial image against published criminal-record datasets to surface potential matches. Didit exposes this service through `POST /v3/database-validation/` so you can verify the submitted data against the authoritative source and receive normalized match results. ## Coverage * **Coverage:** — * **Country:** South Africa * **Service ID:** `zaf_criminal_face_screening` * **Data domain:** Criminal * **Category:** Criminal ## Inputs | Field | Required | Example | | ------------- | -------: | --------------- | | `selfie` | Yes | `@./selfie.jpg` | | `score_level` | No | `standard` | | `max_matches` | No | `10` | | `vendor_data` | No | `user-1234` | * **Required inputs:** `selfie` * **Optional inputs:** `score_level`, `max_matches`, `vendor_data` * **Consent:** Required * **Workflow availability:** Available in workflow * **Coverage:** — * **Price:** \$7.00 per successful query ## Body parameters ISO 3166-1 alpha-3 country code for this database service. Example: `ZAF` Array containing this service ID. Pinning the service keeps the request scoped to this exact database. Example: `zaf_criminal_face_screening` Explicit end-user consent for this service. Example: `true` Selfie image file to upload for biometric database validation. Accepted formats: JPEG, PNG, or WebP. Example: `@./selfie.jpg` `score_level` value required by this database service. Example: `standard` `max_matches` value required by this database service. Example: `10` Your stable user reference for this person, such as your internal user ID. Didit uses it to link standalone checks to the same end user and reduce duplicate-detection noise. Example: `user-1234` ## Input rules & validation notes * Send the fields listed above exactly as captured from the user or document. * Didit validates required fields before calling the database. Requests rejected before source lookup are not charged. ## How to call it ```bash cURL theme={null} curl -X POST "https://verification.didit.me/v3/database-validation/" \ -H "x-api-key: YOUR_API_KEY" \ -F "issuing_state=ZAF" \ -F "services=zaf_criminal_face_screening" \ -F "vendor_data=user-1234" \ -F "consent=true" \ -F "selfie=@./selfie.jpg" ``` Every successful call returns HTTP `200`. The **`outcome_code`** field tells you what actually happened — distinguishing, for example, a real biometric mismatch (`BIOMETRIC_NO_MATCH`) from a selfie that could not be read (`BIOMETRIC_IMAGE_UNUSABLE`). The `status` shown is the default feature status; your configured [Partial Match / No Match actions](/core-technology/database-validation/database-validation-warnings) can override it. **`MATCH`** — The registry confirmed the identity and every checked field matched. ```json 200 OK — MATCH theme={null} { "request_id": "req_01H…", "status": "Approved", "issuing_state": "ZAF", "match_type": "full_match", "validations": [ { "outcome_code": "MATCH", "service_id": "zaf_criminal_face_screening", "service_name": "South Africa - Criminal Screening by Face", "source_data": { "criminal_matches": "sample_value", "face_quality": "sample_value", "request_id": "SAMPLE-12345" }, "validation": { "identification_number": "full_match" } } ] } ``` **`NO_MATCH`** — The registry returned no match for the submitted data. ```json 200 OK — NO_MATCH theme={null} { "request_id": "req_01H…", "status": "Declined", "issuing_state": "ZAF", "match_type": "no_match", "validations": [ { "outcome_code": "NO_MATCH", "service_id": "zaf_criminal_face_screening", "service_name": "South Africa - Criminal Screening by Face", "source_data": { "identification_number": "NO_MATCH" }, "validation": { "identification_number": "no_match" } } ] } ``` **`BIOMETRIC_NO_MATCH`** — The face-match score was below the acceptance threshold - the selfie is not the same person as the registry photo. ```json 200 OK — BIOMETRIC_NO_MATCH theme={null} { "request_id": "req_01H…", "status": "Declined", "issuing_state": "ZAF", "match_type": "no_match", "validations": [ { "outcome_code": "BIOMETRIC_NO_MATCH", "service_id": "zaf_criminal_face_screening", "service_name": "South Africa - Criminal Screening by Face", "source_data": { "identification_number": "NO_MATCH" }, "validation": { "identification_number": "no_match" } } ] } ``` **`BIOMETRIC_IMAGE_UNUSABLE`** — The selfie could not be processed (empty, no face, low quality, or the registry could not read it). Prompt the user to retake the selfie. ```json 200 OK — BIOMETRIC_IMAGE_UNUSABLE theme={null} { "request_id": "req_01H…", "status": "In Review", "issuing_state": "ZAF", "match_type": "no_match", "validations": [ { "outcome_code": "BIOMETRIC_IMAGE_UNUSABLE", "service_id": "zaf_criminal_face_screening", "service_name": "South Africa - Criminal Screening by Face", "source_data": { "identification_number": "NO_MATCH" }, "validation": { "identification_number": "no_match" } } ] } ``` ## Returned data The exact fields surfaced in `source_data` depend on what the registry returns. The generated example for `zaf_criminal_face_screening` currently documents this normalized shape: * `criminal_matches` * `face_quality` * `request_id` ## Pricing & SLAs South Africa - Criminal Screening by Face queries are billed only when Didit receives a conclusive result from the validation source. * **Per-call price:** \$7.00 USD. * **Billing:** per successful query. You are not charged when the registry is unreachable, when required fields are missing, or when the request is rejected before reaching the source. * **Latency:** typical p95 \< 2 s. * **Availability:** 99.9% per quarter on Didit's side; downstream source availability varies by country and dataset. ## Continue reading * [South Africa Database Validation overview](/api-reference/database-validation/south-africa) * [Database Validation overview](/core-technology/database-validation/overview) * [Outcome Codes](/core-technology/database-validation/database-validation-outcome-codes) # South Africa - DHA Fingerprint Match Source: https://docs.didit.me/api-reference/database-validation/south-africa/dha-fingerprint-match POST /v3/database-validation/ Verifies provided fingerprint images against the Department of Home Affairs fingerprint register. Authoritative real-time identity lookup for South Africa. Real-time lookup, pay-per-call.
Verifies provided fingerprint images against the Department of Home Affairs fingerprint register. Didit exposes this service through `POST /v3/database-validation/` so you can verify the submitted data against the authoritative source and receive normalized match results. ## Coverage * **Coverage:** — * **Country:** South Africa * **Service ID:** `zaf_dha_fingerprint_match` * **Data domain:** Biometric * **Category:** Government ## Inputs | Field | Required | Example | | ------------- | -------: | ---------------------- | | `national_id` | Yes | `SAMPLE-NID-12345` | | `right_thumb` | Yes | `RIGHT_THUMB_TEMPLATE` | | `left_thumb` | Yes | `LEFT_THUMB_TEMPLATE` | | `vendor_data` | No | `user-1234` | * **Required inputs:** `national_id`, `right_thumb`, `left_thumb` * **Optional inputs:** `vendor_data` * **Consent:** Required * **Workflow availability:** Standalone API only * **Coverage:** — * **Price:** \$1.10 per successful query This service needs an input no workflow step can produce (a biometric capture, a signed artifact, a live one-time code), so it is available only on the standalone API, where you supply the values directly. ## Body parameters ISO 3166-1 alpha-3 country code for this database service. Example: `ZAF` Array containing this service ID. Pinning the service keeps the request scoped to this exact database. Example: `zaf_dha_fingerprint_match` Explicit end-user consent for this service. Example: `true` National identity number for this service. Example: `SAMPLE-NID-12345` `right_thumb` value required by this database service. Example: `RIGHT_THUMB_TEMPLATE` `left_thumb` value required by this database service. Example: `LEFT_THUMB_TEMPLATE` Your stable user reference for this person, such as your internal user ID. Didit uses it to link standalone checks to the same end user and reduce duplicate-detection noise. Example: `user-1234` ## Input rules & validation notes * Send the fields listed above exactly as captured from the user or document. * Didit validates required fields before calling the database. Requests rejected before source lookup are not charged. ## How to call it ```bash cURL theme={null} curl -X POST "https://verification.didit.me/v3/database-validation/" \ -H "x-api-key: YOUR_API_KEY" \ -F "issuing_state=ZAF" \ -F "services=zaf_dha_fingerprint_match" \ -F "vendor_data=user-1234" \ -F "consent=true" \ -F "national_id=SAMPLE-NID-12345" \ -F "right_thumb=RIGHT_THUMB_TEMPLATE" \ -F "left_thumb=LEFT_THUMB_TEMPLATE" ``` Every successful call returns HTTP `200`. The **`outcome_code`** field tells you what actually happened — distinguishing, for example, a real biometric mismatch (`BIOMETRIC_NO_MATCH`) from a selfie that could not be read (`BIOMETRIC_IMAGE_UNUSABLE`). The `status` shown is the default feature status; your configured [Partial Match / No Match actions](/core-technology/database-validation/database-validation-warnings) can override it. **`MATCH`** — The registry confirmed the identity and every checked field matched. ```json 200 OK — MATCH theme={null} { "request_id": "req_01H…", "status": "Approved", "issuing_state": "ZAF", "match_type": "full_match", "validations": [ { "outcome_code": "MATCH", "service_id": "zaf_dha_fingerprint_match", "service_name": "South Africa - DHA Fingerprint Match", "source_data": { "identification_number": "SAMPLE-ID-12345" }, "validation": { "identification_number": "full_match" } } ] } ``` **`NO_MATCH`** — The registry returned no match for the submitted data. ```json 200 OK — NO_MATCH theme={null} { "request_id": "req_01H…", "status": "Declined", "issuing_state": "ZAF", "match_type": "no_match", "validations": [ { "outcome_code": "NO_MATCH", "service_id": "zaf_dha_fingerprint_match", "service_name": "South Africa - DHA Fingerprint Match", "source_data": { "identification_number": "NO_MATCH" }, "validation": { "identification_number": "no_match" } } ] } ``` ## Returned data The exact fields surfaced in `source_data` depend on what the registry returns. The generated example for `zaf_dha_fingerprint_match` currently documents this normalized shape: * `identification_number` ## Pricing & SLAs South Africa - DHA Fingerprint Match queries are billed only when Didit receives a conclusive result from the validation source. * **Per-call price:** \$1.10 USD. * **Billing:** per successful query. You are not charged when the registry is unreachable, when required fields are missing, or when the request is rejected before reaching the source. * **Latency:** typical p95 \< 2 s. * **Availability:** 99.9% per quarter on Didit's side; downstream source availability varies by country and dataset. ## Continue reading * [South Africa Database Validation overview](/api-reference/database-validation/south-africa) * [Database Validation overview](/core-technology/database-validation/overview) * [Outcome Codes](/core-technology/database-validation/database-validation-outcome-codes) # South Africa - DHA Photo Retrieval Source: https://docs.didit.me/api-reference/database-validation/south-africa/dha-photo POST /v3/database-validation/ Retrieves the registered Department of Home Affairs photograph for a South African ID number. Authoritative real-time identity lookup for South Africa. Real-time lookup, pay-per-call.
Retrieves the registered Department of Home Affairs photograph for a South African ID number. Didit exposes this service through `POST /v3/database-validation/` so you can verify the submitted data against the authoritative source and receive normalized match results. ## Coverage * **Coverage:** — * **Country:** South Africa * **Service ID:** `zaf_dha_photo` * **Data domain:** Biometric * **Category:** Government ## Inputs | Field | Required | Example | | ------------- | -------: | ------------------ | | `national_id` | Yes | `SAMPLE-NID-12345` | | `vendor_data` | No | `user-1234` | * **Required inputs:** `national_id` * **Optional inputs:** `vendor_data` * **Consent:** Required * **Workflow availability:** Available in workflow * **Coverage:** — * **Price:** \$1.10 per successful query ## Body parameters ISO 3166-1 alpha-3 country code for this database service. Example: `ZAF` Array containing this service ID. Pinning the service keeps the request scoped to this exact database. Example: `zaf_dha_photo` Explicit end-user consent for this service. Example: `true` National identity number for this service. Example: `SAMPLE-NID-12345` Your stable user reference for this person, such as your internal user ID. Didit uses it to link standalone checks to the same end user and reduce duplicate-detection noise. Example: `user-1234` ## Input rules & validation notes * Send the fields listed above exactly as captured from the user or document. * Didit validates required fields before calling the database. Requests rejected before source lookup are not charged. ## How to call it ```bash cURL theme={null} curl -X POST "https://verification.didit.me/v3/database-validation/" \ -H "x-api-key: YOUR_API_KEY" \ -F "issuing_state=ZAF" \ -F "services=zaf_dha_photo" \ -F "vendor_data=user-1234" \ -F "consent=true" \ -F "national_id=SAMPLE-NID-12345" ``` Every successful call returns HTTP `200`. The **`outcome_code`** field tells you what actually happened — distinguishing, for example, a real biometric mismatch (`BIOMETRIC_NO_MATCH`) from a selfie that could not be read (`BIOMETRIC_IMAGE_UNUSABLE`). The `status` shown is the default feature status; your configured [Partial Match / No Match actions](/core-technology/database-validation/database-validation-warnings) can override it. **`MATCH`** — The registry confirmed the identity and every checked field matched. ```json 200 OK — MATCH theme={null} { "request_id": "req_01H…", "status": "Approved", "issuing_state": "ZAF", "match_type": "full_match", "validations": [ { "outcome_code": "MATCH", "service_id": "zaf_dha_photo", "service_name": "South Africa - DHA Photo Retrieval", "source_data": { "birth_place_country_code": "sample_value", "deceased": "sample_value", "first_name": "John", "id_blocked": false, "identification_number": "SAMPLE-ID-12345", "last_name": "Doe", "marital_status": "sample_value", "on_hanis_biometric_register": "sample_value", "on_national_population_register": "sample_value", "photo_base64": "sample_value", "smart_card_issued": "sample_value", "transaction_number": "SAMPLE-12345" }, "validation": { "identification_number": "full_match" } } ] } ``` **`NO_MATCH`** — The registry returned no match for the submitted data. ```json 200 OK — NO_MATCH theme={null} { "request_id": "req_01H…", "status": "Declined", "issuing_state": "ZAF", "match_type": "no_match", "validations": [ { "outcome_code": "NO_MATCH", "service_id": "zaf_dha_photo", "service_name": "South Africa - DHA Photo Retrieval", "source_data": { "identification_number": "NO_MATCH" }, "validation": { "identification_number": "no_match" } } ] } ``` ## Returned data The exact fields surfaced in `source_data` depend on what the registry returns. The generated example for `zaf_dha_photo` currently documents this normalized shape: * `birth_place_country_code` * `deceased` * `first_name` * `id_blocked` * `identification_number` * `last_name` * `marital_status` * `on_hanis_biometric_register` * `on_national_population_register` * `photo_base64` * `smart_card_issued` * `transaction_number` ## Pricing & SLAs South Africa - DHA Photo Retrieval queries are billed only when Didit receives a conclusive result from the validation source. * **Per-call price:** \$1.10 USD. * **Billing:** per successful query. You are not charged when the registry is unreachable, when required fields are missing, or when the request is rejected before reaching the source. * **Latency:** typical p95 \< 2 s. * **Availability:** 99.9% per quarter on Didit's side; downstream source availability varies by country and dataset. ## Continue reading * [South Africa Database Validation overview](/api-reference/database-validation/south-africa) * [Database Validation overview](/core-technology/database-validation/overview) * [Outcome Codes](/core-technology/database-validation/database-validation-outcome-codes) # South Africa - Driving License Verification Source: https://docs.didit.me/api-reference/database-validation/south-africa/drivers-license POST /v3/database-validation/ Verifies a South African driving license against the NATIS / Department of Transport register. Authoritative real-time identity lookup for South Africa. Real-time lookup, pay-per-call.
Verifies a South African driving license against the NATIS / Department of Transport register. Didit exposes this service through `POST /v3/database-validation/` so you can verify the submitted data against the authoritative source and receive normalized match results. ## Coverage * **Coverage:** — * **Country:** South Africa * **Service ID:** `zaf_drivers_license` * **Data domain:** Identity * **Category:** DriverLicence ## Inputs | Field | Required | Example | | ---------------- | -------: | ------------------ | | `national_id` | Yes | `SAMPLE-NID-12345` | | `last_name` | Yes | `Doe` | | `initials` | Yes | `JD` | | `licence_number` | Yes | `LIC123456` | | `first_name` | No | `John` | | `date_of_birth` | No | `1990-01-01` | | `vendor_data` | No | `user-1234` | * **Required inputs:** `national_id`, `last_name`, `initials`, `licence_number` * **Optional inputs:** `first_name`, `date_of_birth`, `vendor_data` * **Consent:** Not required * **Workflow availability:** Available in workflow with field mapping * **Coverage:** — * **Price:** \$0.70 per successful query In a workflow, `initials` and `licence_number` are not printed on an identity document, so no step produces them on their own. Collect them from a Questionnaire answer, a Document AI extraction field, or a value you send when you create the session, and map each one on the Database Validation step. Until they are mapped the workflow editor shows this service disabled and names the missing input; at run time a missing input means the check is skipped before any query, so you are never billed for a database that could not be asked. ## Body parameters ISO 3166-1 alpha-3 country code for this database service. Example: `ZAF` Array containing this service ID. Pinning the service keeps the request scoped to this exact database. Example: `zaf_drivers_license` National identity number for this service. Example: `SAMPLE-NID-12345` Family name to validate. Example: `Doe` `initials` value required by this database service. Example: `JD` `licence_number` value required by this database service. Example: `LIC123456` Given name to validate. Example: `John` Date of birth in `YYYY-MM-DD` format. Example: `1990-01-01` Your stable user reference for this person, such as your internal user ID. Didit uses it to link standalone checks to the same end user and reduce duplicate-detection noise. Example: `user-1234` ## Input rules & validation notes * Send the fields listed above exactly as captured from the user or document. * Didit validates required fields before calling the database. Requests rejected before source lookup are not charged. ## How to call it ```bash cURL theme={null} curl -X POST "https://verification.didit.me/v3/database-validation/" \ -H "x-api-key: YOUR_API_KEY" \ -F "issuing_state=ZAF" \ -F "services=zaf_drivers_license" \ -F "vendor_data=user-1234" \ -F "national_id=SAMPLE-NID-12345" \ -F "last_name=Doe" \ -F "initials=JD" \ -F "licence_number=LIC123456" ``` Every successful call returns HTTP `200`. The **`outcome_code`** field tells you what actually happened — distinguishing, for example, a real biometric mismatch (`BIOMETRIC_NO_MATCH`) from a selfie that could not be read (`BIOMETRIC_IMAGE_UNUSABLE`). The `status` shown is the default feature status; your configured [Partial Match / No Match actions](/core-technology/database-validation/database-validation-warnings) can override it. **`MATCH`** — The registry confirmed the identity and every checked field matched. ```json 200 OK — MATCH theme={null} { "request_id": "req_01H…", "status": "Approved", "issuing_state": "ZAF", "match_type": "full_match", "validations": [ { "outcome_code": "MATCH", "service_id": "zaf_drivers_license", "service_name": "South Africa - Driving License Verification", "source_data": { "date_of_birth": "1990-01-01", "first_name": "John", "identification_number": "SAMPLE-ID-12345", "last_name": "Doe" }, "validation": { "full_name": "full_match", "identification_number": "full_match" } } ] } ``` **`PARTIAL_MATCH`** — The identification number was found but one or more personal fields (usually name or date of birth) did not fully match. ```json 200 OK — PARTIAL_MATCH theme={null} { "request_id": "req_01H…", "status": "In Review", "issuing_state": "ZAF", "match_type": "partial_match", "validations": [ { "outcome_code": "PARTIAL_MATCH", "service_id": "zaf_drivers_license", "service_name": "South Africa - Driving License Verification", "source_data": { "date_of_birth": "1990-01-01", "first_name": "John", "identification_number": "SAMPLE-ID-12345", "last_name": "Doe" }, "validation": { "full_name": "no_match", "identification_number": "full_match" } } ] } ``` **`NO_MATCH`** — The registry returned no match for the submitted data. ```json 200 OK — NO_MATCH theme={null} { "request_id": "req_01H…", "status": "Declined", "issuing_state": "ZAF", "match_type": "no_match", "validations": [ { "outcome_code": "NO_MATCH", "service_id": "zaf_drivers_license", "service_name": "South Africa - Driving License Verification", "source_data": { "full_name": "NO_MATCH", "identification_number": "NO_MATCH" }, "validation": { "full_name": "no_match", "identification_number": "no_match" } } ] } ``` ## Returned data The exact fields surfaced in `source_data` depend on what the registry returns. The generated example for `zaf_drivers_license` currently documents this normalized shape: * `date_of_birth` * `first_name` * `identification_number` * `last_name` ## Pricing & SLAs South Africa - Driving License Verification queries are billed only when Didit receives a conclusive result from the validation source. * **Per-call price:** \$0.70 USD. * **Billing:** per successful query. You are not charged when the registry is unreachable, when required fields are missing, or when the request is rejected before reaching the source. * **Latency:** typical p95 \< 2 s. * **Availability:** 99.9% per quarter on Didit's side; downstream source availability varies by country and dataset. ## What a MATCH confirms This is a **record match against the driving-licence register**, not a licence-standing check. You send a South African ID number and a licence number (plus surname and initials as cross-checks); the register is asked whether it holds that licence for that person, and `validation` reports how each submitted field compared with the record. A `MATCH` therefore means *this licence number belongs to this person on the register*. It does not assert that the licence is currently valid to drive on. `source_data` carries the record the register returned: * **`identification_number`** - the licence number held on the record. * **`first_name`**, **`last_name`** - the forenames and surname on the record. * **`vehicle_codes`** - the vehicle codes (licence classes) the record carries, e.g. `EB`, `C1`. * **`expiration_date`** - the expiry date of the licence card on the record. **What is not returned.** There is no suspension, cancellation, withdrawal, endorsement or demerit-point field: the register does not answer those through this service, so a `MATCH` must never be worded to your users as "the licence is valid and in good standing". `expiration_date` is the one standing-adjacent fact you get - compare it with the session date to decide whether the licence has expired, and treat that as a rule of your own rather than as part of the match outcome. If you need to state this in terms and conditions, word it as: Didit confirms the licence details against the national register and returns the licence's classes and expiry date - not that Didit confirms the holder is licensed to drive today. ## Continue reading * [South Africa Database Validation overview](/api-reference/database-validation/south-africa) * [Database Validation overview](/core-technology/database-validation/overview) * [Outcome Codes](/core-technology/database-validation/database-validation-outcome-codes) # South Africa - Fraud Prevention Screening Source: https://docs.didit.me/api-reference/database-validation/south-africa/fraud-prevention POST /v3/database-validation/ Screens an individual against the South African Fraud Prevention Service (SAFPS) watch-list. Authoritative real-time identity lookup for South Africa. Real-time lookup, pay-per-call.
Screens an individual against the South African Fraud Prevention Service (SAFPS) watch-list. Didit exposes this service through `POST /v3/database-validation/` so you can verify the submitted data against the authoritative source and receive normalized match results. ## Coverage * **Coverage:** — * **Country:** South Africa * **Service ID:** `zaf_fraud_prevention` * **Data domain:** Background * **Category:** Background ## Inputs | Field | Required | Example | | --------------------- | -------: | ---------------------- | | `national_id` | No | `SAMPLE-NID-12345` | | `bank_account_number` | No | `1234567890` | | `phone_number` | No | `+15550101000` | | `email` | No | `john.doe@example.com` | | `vendor_data` | No | `user-1234` | * **Required inputs:** — * **Optional inputs:** `national_id`, `bank_account_number`, `phone_number`, `email`, `vendor_data` * **Consent:** Required * **Workflow availability:** Available in workflow * **Coverage:** — * **Price:** \$0.30 per successful query ## Body parameters ISO 3166-1 alpha-3 country code for this database service. Example: `ZAF` Array containing this service ID. Pinning the service keeps the request scoped to this exact database. Example: `zaf_fraud_prevention` Explicit end-user consent for this service. Example: `true` National identity number for this service. Example: `SAMPLE-NID-12345` `bank_account_number` value required by this database service. Example: `1234567890` `phone_number` value required by this database service. Example: `+15550101000` Email address. Example: `john.doe@example.com` Your stable user reference for this person, such as your internal user ID. Didit uses it to link standalone checks to the same end user and reduce duplicate-detection noise. Example: `user-1234` ## Input rules & validation notes * Send the fields listed above exactly as captured from the user or document. * Didit validates required fields before calling the database. Requests rejected before source lookup are not charged. ## How to call it ```bash cURL theme={null} curl -X POST "https://verification.didit.me/v3/database-validation/" \ -H "x-api-key: YOUR_API_KEY" \ -F "issuing_state=ZAF" \ -F "services=zaf_fraud_prevention" \ -F "vendor_data=user-1234" \ -F "consent=true" ``` Every successful call returns HTTP `200`. The **`outcome_code`** field tells you what actually happened — distinguishing, for example, a real biometric mismatch (`BIOMETRIC_NO_MATCH`) from a selfie that could not be read (`BIOMETRIC_IMAGE_UNUSABLE`). The `status` shown is the default feature status; your configured [Partial Match / No Match actions](/core-technology/database-validation/database-validation-warnings) can override it. **`MATCH`** — The registry confirmed the identity and every checked field matched. ```json 200 OK — MATCH theme={null} { "request_id": "req_01H…", "status": "Approved", "issuing_state": "ZAF", "match_type": "full_match", "validations": [ { "outcome_code": "MATCH", "service_id": "zaf_fraud_prevention", "service_name": "South Africa - Fraud Prevention Screening", "source_data": { "fraud_listings": "sample_value", "identification_number": "SAMPLE-ID-12345" }, "validation": { "identification_number": "full_match" } } ] } ``` **`NO_MATCH`** — The registry returned no match for the submitted data. ```json 200 OK — NO_MATCH theme={null} { "request_id": "req_01H…", "status": "Declined", "issuing_state": "ZAF", "match_type": "no_match", "validations": [ { "outcome_code": "NO_MATCH", "service_id": "zaf_fraud_prevention", "service_name": "South Africa - Fraud Prevention Screening", "source_data": { "identification_number": "NO_MATCH" }, "validation": { "identification_number": "no_match" } } ] } ``` ## Returned data The exact fields surfaced in `source_data` depend on what the registry returns. The generated example for `zaf_fraud_prevention` currently documents this normalized shape: * `fraud_listings` * `identification_number` ## Pricing & SLAs South Africa - Fraud Prevention Screening queries are billed only when Didit receives a conclusive result from the validation source. * **Per-call price:** \$0.30 USD. * **Billing:** per successful query. You are not charged when the registry is unreachable, when required fields are missing, or when the request is rejected before reaching the source. * **Latency:** typical p95 \< 2 s. * **Availability:** 99.9% per quarter on Didit's side; downstream source availability varies by country and dataset. ## Continue reading * [South Africa Database Validation overview](/api-reference/database-validation/south-africa) * [Database Validation overview](/core-technology/database-validation/overview) * [Outcome Codes](/core-technology/database-validation/database-validation-outcome-codes) # South Africa National ID (DHA) Source: https://docs.didit.me/api-reference/database-validation/south-africa/national-id POST /v3/database-validation/ Verifies input data against the Department of Home Affairs (DHA) registry in South Africa. Authoritative real-time identity lookup for South Africa. Real-time lookup, pay-per-call.
Verifies input data against the Department of Home Affairs (DHA) registry in South Africa. Didit exposes this service through `POST /v3/database-validation/` so you can verify the submitted data against the authoritative source and receive normalized match results. ## Coverage * **Coverage:** \~ 100% * **Country:** South Africa * **Service ID:** `zaf_africa_national_id` * **Data domain:** Identity * **Category:** NationalIDRegistry ## Inputs | Field | Required | Example | | --------------- | -------: | ------------------ | | `first_name` | Yes | `John` | | `last_name` | Yes | `Doe` | | `date_of_birth` | Yes | `1990-01-01` | | `national_id` | Yes | `SAMPLE-NID-12345` | | `vendor_data` | No | `user-1234` | * **Required inputs:** `first_name`, `last_name`, `date_of_birth`, `national_id` * **Optional inputs:** `vendor_data` * **Consent:** Not required * **Workflow availability:** Available in workflow * **Coverage:** \~ 100% * **Price:** \$1.10 per successful query ## Body parameters ISO 3166-1 alpha-3 country code for this database service. Example: `ZAF` Array containing this service ID. Pinning the service keeps the request scoped to this exact database. Example: `zaf_africa_national_id` Given name to validate. Example: `John` Family name to validate. Example: `Doe` Date of birth in `YYYY-MM-DD` format. Example: `1990-01-01` National identity number for this service. Example: `SAMPLE-NID-12345` Your stable user reference for this person, such as your internal user ID. Didit uses it to link standalone checks to the same end user and reduce duplicate-detection noise. Example: `user-1234` ## Input rules & validation notes * Send the fields listed above exactly as captured from the user or document. * Didit validates required fields before calling the database. Requests rejected before source lookup are not charged. ## How to call it ```bash cURL theme={null} curl -X POST "https://verification.didit.me/v3/database-validation/" \ -H "x-api-key: YOUR_API_KEY" \ -F "issuing_state=ZAF" \ -F "services=zaf_africa_national_id" \ -F "vendor_data=user-1234" \ -F "first_name=John" \ -F "last_name=Doe" \ -F "date_of_birth=1990-01-01" \ -F "national_id=SAMPLE-NID-12345" ``` Every successful call returns HTTP `200`. The **`outcome_code`** field tells you what actually happened — distinguishing, for example, a real biometric mismatch (`BIOMETRIC_NO_MATCH`) from a selfie that could not be read (`BIOMETRIC_IMAGE_UNUSABLE`). The `status` shown is the default feature status; your configured [Partial Match / No Match actions](/core-technology/database-validation/database-validation-warnings) can override it. **`MATCH`** — The registry confirmed the identity and every checked field matched. ```json 200 OK — MATCH theme={null} { "request_id": "req_01H…", "status": "Approved", "issuing_state": "ZAF", "match_type": "full_match", "validations": [ { "outcome_code": "MATCH", "service_id": "zaf_africa_national_id", "service_name": "South Africa National ID (DHA)", "source_data": { "first_name": "John", "identification_number": "SAMPLE-ID-12345", "last_name": "Doe", "marital_status": "sample_value" }, "validation": { "date_of_birth": "full_match", "full_name": "full_match", "identification_number": "full_match" } } ] } ``` **`PARTIAL_MATCH`** — The identification number was found but one or more personal fields (usually name or date of birth) did not fully match. ```json 200 OK — PARTIAL_MATCH theme={null} { "request_id": "req_01H…", "status": "In Review", "issuing_state": "ZAF", "match_type": "partial_match", "validations": [ { "outcome_code": "PARTIAL_MATCH", "service_id": "zaf_africa_national_id", "service_name": "South Africa National ID (DHA)", "source_data": { "first_name": "John", "identification_number": "SAMPLE-ID-12345", "last_name": "Doe", "marital_status": "sample_value" }, "validation": { "date_of_birth": "full_match", "full_name": "no_match", "identification_number": "full_match" } } ] } ``` **`NO_MATCH`** — The registry returned no match for the submitted data. ```json 200 OK — NO_MATCH theme={null} { "request_id": "req_01H…", "status": "Declined", "issuing_state": "ZAF", "match_type": "no_match", "validations": [ { "outcome_code": "NO_MATCH", "service_id": "zaf_africa_national_id", "service_name": "South Africa National ID (DHA)", "source_data": { "date_of_birth": "NO_MATCH", "full_name": "NO_MATCH", "identification_number": "NO_MATCH" }, "validation": { "date_of_birth": "no_match", "full_name": "no_match", "identification_number": "no_match" } } ] } ``` **`DOCUMENT_NOT_FOUND`** — The submitted document number does not correspond to any record in the registry. ```json 200 OK — DOCUMENT_NOT_FOUND theme={null} { "request_id": "req_01H…", "status": "Declined", "issuing_state": "ZAF", "match_type": "no_match", "validations": [ { "outcome_code": "DOCUMENT_NOT_FOUND", "service_id": "zaf_africa_national_id", "service_name": "South Africa National ID (DHA)", "source_data": { "date_of_birth": "NO_MATCH", "full_name": "NO_MATCH", "identification_number": "NO_MATCH" }, "validation": { "date_of_birth": "no_match", "full_name": "no_match", "identification_number": "no_match" } } ] } ``` ## Returned data The exact fields surfaced in `source_data` depend on what the registry returns. The generated example for `zaf_africa_national_id` currently documents this normalized shape: * `first_name` * `identification_number` * `last_name` * `marital_status` ## Pricing & SLAs South Africa National ID (DHA) queries are billed only when Didit receives a conclusive result from the validation source. * **Per-call price:** \$1.10 USD. * **Billing:** per successful query. You are not charged when the registry is unreachable, when required fields are missing, or when the request is rejected before reaching the source. * **Latency:** typical p95 \< 2 s. * **Availability:** 99.9% per quarter on Didit's side; downstream source availability varies by country and dataset. ## Continue reading * [South Africa Database Validation overview](/api-reference/database-validation/south-africa) * [Database Validation overview](/core-technology/database-validation/overview) * [Outcome Codes](/core-technology/database-validation/database-validation-outcome-codes) # South Africa - Person Directorships Lookup Source: https://docs.didit.me/api-reference/database-validation/south-africa/person-directorships POST /v3/database-validation/ Returns all CIPC-registered directorships held by a South African individual. Authoritative real-time identity lookup for South Africa. Real-time lookup, pay-per-call.
Returns all CIPC-registered directorships held by a South African individual. Didit exposes this service through `POST /v3/database-validation/` so you can verify the submitted data against the authoritative source and receive normalized match results. ## Coverage * **Coverage:** — * **Country:** South Africa * **Service ID:** `zaf_person_directorships` * **Data domain:** Government * **Category:** CompanyRegister ## Inputs | Field | Required | Example | | ------------- | -------: | ------------------ | | `national_id` | Yes | `SAMPLE-NID-12345` | | `vendor_data` | No | `user-1234` | * **Required inputs:** `national_id` * **Optional inputs:** `vendor_data` * **Consent:** Not required * **Workflow availability:** Available in workflow * **Coverage:** — * **Price:** \$1.20 per successful query ## Body parameters ISO 3166-1 alpha-3 country code for this database service. Example: `ZAF` Array containing this service ID. Pinning the service keeps the request scoped to this exact database. Example: `zaf_person_directorships` National identity number for this service. Example: `SAMPLE-NID-12345` Your stable user reference for this person, such as your internal user ID. Didit uses it to link standalone checks to the same end user and reduce duplicate-detection noise. Example: `user-1234` ## Input rules & validation notes * Send the fields listed above exactly as captured from the user or document. * Didit validates required fields before calling the database. Requests rejected before source lookup are not charged. ## How to call it ```bash cURL theme={null} curl -X POST "https://verification.didit.me/v3/database-validation/" \ -H "x-api-key: YOUR_API_KEY" \ -F "issuing_state=ZAF" \ -F "services=zaf_person_directorships" \ -F "vendor_data=user-1234" \ -F "national_id=SAMPLE-NID-12345" ``` Every successful call returns HTTP `200`. The **`outcome_code`** field tells you what actually happened — distinguishing, for example, a real biometric mismatch (`BIOMETRIC_NO_MATCH`) from a selfie that could not be read (`BIOMETRIC_IMAGE_UNUSABLE`). The `status` shown is the default feature status; your configured [Partial Match / No Match actions](/core-technology/database-validation/database-validation-warnings) can override it. **`MATCH`** — The registry confirmed the identity and every checked field matched. ```json 200 OK — MATCH theme={null} { "request_id": "req_01H…", "status": "Approved", "issuing_state": "ZAF", "match_type": "full_match", "validations": [ { "outcome_code": "MATCH", "service_id": "zaf_person_directorships", "service_name": "South Africa - Person Directorships Lookup", "source_data": { "directorships": "sample_value", "identification_number": "SAMPLE-ID-12345" }, "validation": { "identification_number": "full_match" } } ] } ``` **`NO_MATCH`** — The registry returned no match for the submitted data. ```json 200 OK — NO_MATCH theme={null} { "request_id": "req_01H…", "status": "Declined", "issuing_state": "ZAF", "match_type": "no_match", "validations": [ { "outcome_code": "NO_MATCH", "service_id": "zaf_person_directorships", "service_name": "South Africa - Person Directorships Lookup", "source_data": { "identification_number": "NO_MATCH" }, "validation": { "identification_number": "no_match" } } ] } ``` ## Returned data The exact fields surfaced in `source_data` depend on what the registry returns. The generated example for `zaf_person_directorships` currently documents this normalized shape: * `directorships` * `identification_number` ## Pricing & SLAs South Africa - Person Directorships Lookup queries are billed only when Didit receives a conclusive result from the validation source. * **Per-call price:** \$1.20 USD. * **Billing:** per successful query. You are not charged when the registry is unreachable, when required fields are missing, or when the request is rejected before reaching the source. * **Latency:** typical p95 \< 2 s. * **Availability:** 99.9% per quarter on Didit's side; downstream source availability varies by country and dataset. ## Continue reading * [South Africa Database Validation overview](/api-reference/database-validation/south-africa) * [Database Validation overview](/core-technology/database-validation/overview) * [Outcome Codes](/core-technology/database-validation/database-validation-outcome-codes) # South Africa - Refugee File Verification Source: https://docs.didit.me/api-reference/database-validation/south-africa/refugee POST /v3/database-validation/ Verifies a refugee file number against the South African Department of Home Affairs refugee register. Authoritative real-time identity lookup for South Africa. Real-time lookup, pay-per-call.
Verifies a refugee file number against the South African Department of Home Affairs refugee register. Didit exposes this service through `POST /v3/database-validation/` so you can verify the submitted data against the authoritative source and receive normalized match results. ## Coverage * **Coverage:** — * **Country:** South Africa * **Service ID:** `zaf_refugee` * **Data domain:** Identity * **Category:** Government ## Inputs | Field | Required | Example | | --------------------- | -------: | ---------------------- | | `refugee_file_number` | Yes | `RF123456` | | `phone_number` | No | `+15550101000` | | `email` | No | `john.doe@example.com` | | `vendor_data` | No | `user-1234` | * **Required inputs:** `refugee_file_number` * **Optional inputs:** `phone_number`, `email`, `vendor_data` * **Consent:** Not required * **Workflow availability:** Available in workflow with field mapping * **Coverage:** — * **Price:** \$1.10 per successful query In a workflow, `refugee_file_number` is not printed on an identity document, so no step produces it on its own. Collect it from a Questionnaire answer, a Document AI extraction field, or a value you send when you create the session, and map it on the Database Validation step. Until it is mapped the workflow editor shows this service disabled and names the missing input; at run time a missing input means the check is skipped before any query, so you are never billed for a database that could not be asked. ## Body parameters ISO 3166-1 alpha-3 country code for this database service. Example: `ZAF` Array containing this service ID. Pinning the service keeps the request scoped to this exact database. Example: `zaf_refugee` `refugee_file_number` value required by this database service. Example: `RF123456` `phone_number` value required by this database service. Example: `+15550101000` Email address. Example: `john.doe@example.com` Your stable user reference for this person, such as your internal user ID. Didit uses it to link standalone checks to the same end user and reduce duplicate-detection noise. Example: `user-1234` ## Input rules & validation notes * Send the fields listed above exactly as captured from the user or document. * Didit validates required fields before calling the database. Requests rejected before source lookup are not charged. ## How to call it ```bash cURL theme={null} curl -X POST "https://verification.didit.me/v3/database-validation/" \ -H "x-api-key: YOUR_API_KEY" \ -F "issuing_state=ZAF" \ -F "services=zaf_refugee" \ -F "vendor_data=user-1234" \ -F "refugee_file_number=RF123456" ``` Every successful call returns HTTP `200`. The **`outcome_code`** field tells you what actually happened — distinguishing, for example, a real biometric mismatch (`BIOMETRIC_NO_MATCH`) from a selfie that could not be read (`BIOMETRIC_IMAGE_UNUSABLE`). The `status` shown is the default feature status; your configured [Partial Match / No Match actions](/core-technology/database-validation/database-validation-warnings) can override it. **`MATCH`** — The registry confirmed the identity and every checked field matched. ```json 200 OK — MATCH theme={null} { "request_id": "req_01H…", "status": "Approved", "issuing_state": "ZAF", "match_type": "full_match", "validations": [ { "outcome_code": "MATCH", "service_id": "zaf_refugee", "service_name": "South Africa - Refugee File Verification", "source_data": {}, "validation": { "identification_number": "full_match" } } ] } ``` **`NO_MATCH`** — The registry returned no match for the submitted data. ```json 200 OK — NO_MATCH theme={null} { "request_id": "req_01H…", "status": "Declined", "issuing_state": "ZAF", "match_type": "no_match", "validations": [ { "outcome_code": "NO_MATCH", "service_id": "zaf_refugee", "service_name": "South Africa - Refugee File Verification", "source_data": { "identification_number": "NO_MATCH" }, "validation": { "identification_number": "no_match" } } ] } ``` ## Returned data The exact fields surfaced in `source_data` depend on what the registry returns. The generated example for `zaf_refugee` currently documents this normalized shape: * Varies by registry response. ## Pricing & SLAs South Africa - Refugee File Verification queries are billed only when Didit receives a conclusive result from the validation source. * **Per-call price:** \$1.10 USD. * **Billing:** per successful query. You are not charged when the registry is unreachable, when required fields are missing, or when the request is rejected before reaching the source. * **Latency:** typical p95 \< 2 s. * **Availability:** 99.9% per quarter on Didit's side; downstream source availability varies by country and dataset. ## Continue reading * [South Africa Database Validation overview](/api-reference/database-validation/south-africa) * [Database Validation overview](/core-technology/database-validation/overview) * [Outcome Codes](/core-technology/database-validation/database-validation-outcome-codes) # South Africa - Vehicle Ownership Verification Source: https://docs.didit.me/api-reference/database-validation/south-africa/vehicle-ownership POST /v3/database-validation/ Confirms that a South African individual is the registered owner of a given vehicle via the NATIS vehicle register. Authoritative real-time identity lookup for South Africa. Real-time lookup, pay-per-call.
Confirms that a South African individual is the registered owner of a given vehicle via the NATIS vehicle register. Didit exposes this service through `POST /v3/database-validation/` so you can verify the submitted data against the authoritative source and receive normalized match results. ## Coverage * **Coverage:** — * **Country:** South Africa * **Service ID:** `zaf_vehicle_ownership` * **Data domain:** Government * **Category:** Other ## Inputs | Field | Required | Example | | ------------------------- | -------: | ------------------- | | `national_id` | Yes | `SAMPLE-NID-12345` | | `vehicle_register_number` | Yes | `VRN123456` | | `vehicle_licence_plate` | Yes | `ABC123GP` | | `vin` | Yes | `1HGCM82633A004352` | | `vendor_data` | No | `user-1234` | * **Required inputs:** `national_id`, `vehicle_register_number`, `vehicle_licence_plate`, `vin` * **Optional inputs:** `vendor_data` * **Consent:** Not required * **Workflow availability:** Available in workflow with field mapping * **Coverage:** — * **Price:** \$2.80 per successful query In a workflow, `vehicle_register_number`, `vehicle_licence_plate` and `vin` are not printed on an identity document, so no step produces them on their own. Collect them from a Questionnaire answer, a Document AI extraction field, or a value you send when you create the session, and map each one on the Database Validation step. Until they are mapped the workflow editor shows this service disabled and names the missing input; at run time a missing input means the check is skipped before any query, so you are never billed for a database that could not be asked. ## Body parameters ISO 3166-1 alpha-3 country code for this database service. Example: `ZAF` Array containing this service ID. Pinning the service keeps the request scoped to this exact database. Example: `zaf_vehicle_ownership` National identity number for this service. Example: `SAMPLE-NID-12345` `vehicle_register_number` value required by this database service. Example: `VRN123456` `vehicle_licence_plate` value required by this database service. Example: `ABC123GP` `vin` value required by this database service. Example: `1HGCM82633A004352` Your stable user reference for this person, such as your internal user ID. Didit uses it to link standalone checks to the same end user and reduce duplicate-detection noise. Example: `user-1234` ## Input rules & validation notes * Send the fields listed above exactly as captured from the user or document. * Didit validates required fields before calling the database. Requests rejected before source lookup are not charged. ## How to call it ```bash cURL theme={null} curl -X POST "https://verification.didit.me/v3/database-validation/" \ -H "x-api-key: YOUR_API_KEY" \ -F "issuing_state=ZAF" \ -F "services=zaf_vehicle_ownership" \ -F "vendor_data=user-1234" \ -F "national_id=SAMPLE-NID-12345" \ -F "vehicle_register_number=VRN123456" \ -F "vehicle_licence_plate=ABC123GP" \ -F "vin=1HGCM82633A004352" ``` Every successful call returns HTTP `200`. The **`outcome_code`** field tells you what actually happened — distinguishing, for example, a real biometric mismatch (`BIOMETRIC_NO_MATCH`) from a selfie that could not be read (`BIOMETRIC_IMAGE_UNUSABLE`). The `status` shown is the default feature status; your configured [Partial Match / No Match actions](/core-technology/database-validation/database-validation-warnings) can override it. **`MATCH`** — The registry confirmed the identity and every checked field matched. ```json 200 OK — MATCH theme={null} { "request_id": "req_01H…", "status": "Approved", "issuing_state": "ZAF", "match_type": "full_match", "validations": [ { "outcome_code": "MATCH", "service_id": "zaf_vehicle_ownership", "service_name": "South Africa - Vehicle Ownership Verification", "source_data": { "identification_number": "SAMPLE-ID-12345" }, "validation": { "identification_number": "full_match" } } ] } ``` **`NO_MATCH`** — The registry returned no match for the submitted data. ```json 200 OK — NO_MATCH theme={null} { "request_id": "req_01H…", "status": "Declined", "issuing_state": "ZAF", "match_type": "no_match", "validations": [ { "outcome_code": "NO_MATCH", "service_id": "zaf_vehicle_ownership", "service_name": "South Africa - Vehicle Ownership Verification", "source_data": { "identification_number": "NO_MATCH" }, "validation": { "identification_number": "no_match" } } ] } ``` ## Returned data The exact fields surfaced in `source_data` depend on what the registry returns. The generated example for `zaf_vehicle_ownership` currently documents this normalized shape: * `identification_number` ## Pricing & SLAs South Africa - Vehicle Ownership Verification queries are billed only when Didit receives a conclusive result from the validation source. * **Per-call price:** \$2.80 USD. * **Billing:** per successful query. You are not charged when the registry is unreachable, when required fields are missing, or when the request is rejected before reaching the source. * **Latency:** typical p95 \< 2 s. * **Availability:** 99.9% per quarter on Didit's side; downstream source availability varies by country and dataset. ## Continue reading * [South Africa Database Validation overview](/api-reference/database-validation/south-africa) * [Database Validation overview](/core-technology/database-validation/overview) * [Outcome Codes](/core-technology/database-validation/database-validation-outcome-codes) # Spain - DNI/NIE verification Source: https://docs.didit.me/api-reference/database-validation/spain/dni POST /v3/database-validation/ Verifies a Spanish DNI / NIE holder's name, date of birth and address against national identity records. Authoritative real-time identity lookup for Spain. Real-time lookup, pay-per-call.
Verifies a Spanish DNI / NIE holder's name, date of birth and address against national identity records. Didit exposes this service through `POST /v3/database-validation/` so you can verify the submitted data against the authoritative source and receive normalized match results. ## Coverage * **Coverage:** \~ 75% * **Country:** Spain * **Service ID:** `esp_dni` * **Data domain:** Identity * **Category:** NationalIDRegistry ## Inputs | Field | Required | Example | | --------------------- | -------: | ------------------- | | `first_name` | Yes | `John` | | `last_name` | Yes | `Doe` | | `date_of_birth` | Yes | `1990-01-01` | | `address.street_1` | Yes | `123 Sample Street` | | `address.postal_code` | Yes | `10001` | | `national_id` | No | `SAMPLE-NID-12345` | | `phone` | No | `+15550101000` | | `address.street_2` | No | `Unit 4` | | `address.city` | No | `Sample City` | | `address.region` | No | `Sample State` | | `vendor_data` | No | `user-1234` | * **Required inputs:** `first_name`, `last_name`, `date_of_birth`, `address.street_1`, `address.postal_code` * **Optional inputs:** `national_id`, `phone`, `address.street_2`, `address.city`, `address.region`, `vendor_data` * **Consent:** Required * **Workflow availability:** Available in workflow * **Coverage:** \~ 75% * **Price:** \$1.26 per successful query ## Body parameters ISO 3166-1 alpha-3 country code for this database service. Example: `ESP` Array containing this service ID. Pinning the service keeps the request scoped to this exact database. Example: `esp_dni` Explicit end-user consent for this service. Example: `true` Given name to validate. Example: `John` Family name to validate. Example: `Doe` Date of birth in `YYYY-MM-DD` format. Example: `1990-01-01` Structured residential address object. Use `street_1`, `street_2`, `city`, `region`, `postal_code`, and `country`. A complete legacy address string is still accepted but not recommended. Example: `{"street_1":"123 Sample Street","street_2":"Unit 4","city":"Sample City","region":"Sample State","postal_code":"10001","country":"US"}` National identity number for this service. Example: `SAMPLE-NID-12345` Phone number in international format. Example: `+15550101000` Your stable user reference for this person, such as your internal user ID. Didit uses it to link standalone checks to the same end user and reduce duplicate-detection noise. Example: `user-1234` ## Input rules & validation notes * For address services, send structured address fields instead of a single `address` string when possible. * `address.street_1` is the street address, including street number and street type. * `address.street_2` is apartment, unit, building, floor, or extra address line. Send it only when you have it. * `address.city` is city, suburb, district, locality, or neighborhood. * `address.region` is state, province, region, or town. * `address.postal_code` is postcode or postal code. * Address-based database services require at least street address and postal code; requests rejected before source lookup are not charged. ## How to call it ```bash cURL theme={null} curl -X POST "https://verification.didit.me/v3/database-validation/" \ -H "x-api-key: YOUR_API_KEY" \ -F "issuing_state=ESP" \ -F "services=esp_dni" \ -F "vendor_data=user-1234" \ -F "consent=true" \ -F "first_name=John" \ -F "last_name=Doe" \ -F "date_of_birth=1990-01-01" \ -F 'address={"street_1":"123 Sample Street","street_2":"Unit 4","city":"Sample City","region":"Sample State","postal_code":"10001","country":"US"}' ``` Every successful call returns HTTP `200`. The **`outcome_code`** field tells you what actually happened — distinguishing, for example, a real biometric mismatch (`BIOMETRIC_NO_MATCH`) from a selfie that could not be read (`BIOMETRIC_IMAGE_UNUSABLE`). The `status` shown is the default feature status; your configured [Partial Match / No Match actions](/core-technology/database-validation/database-validation-warnings) can override it. **`MATCH`** — The registry confirmed the identity and every checked field matched. ```json 200 OK — MATCH theme={null} { "request_id": "req_01H…", "status": "Approved", "issuing_state": "ESP", "match_type": "full_match", "validations": [ { "outcome_code": "MATCH", "service_id": "esp_dni", "service_name": "Spain - DNI/NIE verification", "source_data": { "address_match_score": "1.000", "date_of_birth": "1990-01-01", "first_name": "John", "full_name": "John Doe", "identification_number": "SAMPLE-ID-12345", "last_name": "Doe", "name_match_score": "1.000", "verifications": { "address": true, "date_of_birth": true, "full_name": true } }, "validation": { "address": "full_match", "date_of_birth": "full_match", "full_name": "full_match" } } ] } ``` **`PARTIAL_MATCH`** — The identification number was found but one or more personal fields (usually name or date of birth) did not fully match. ```json 200 OK — PARTIAL_MATCH theme={null} { "request_id": "req_01H…", "status": "In Review", "issuing_state": "ESP", "match_type": "partial_match", "validations": [ { "outcome_code": "PARTIAL_MATCH", "service_id": "esp_dni", "service_name": "Spain - DNI/NIE verification", "source_data": { "address_match_score": "1.000", "date_of_birth": "1990-01-01", "first_name": "John", "full_name": "John Doe", "identification_number": "SAMPLE-ID-12345", "last_name": "Doe", "name_match_score": "1.000", "verifications": { "address": true, "date_of_birth": true, "full_name": false } }, "validation": { "address": "full_match", "date_of_birth": "full_match", "full_name": "no_match" } } ] } ``` **`NO_MATCH`** — The registry returned no match for the submitted data. ```json 200 OK — NO_MATCH theme={null} { "request_id": "req_01H…", "status": "Declined", "issuing_state": "ESP", "match_type": "no_match", "validations": [ { "outcome_code": "NO_MATCH", "service_id": "esp_dni", "service_name": "Spain - DNI/NIE verification", "source_data": { "address": "NO_MATCH", "date_of_birth": "NO_MATCH", "full_name": "NO_MATCH" }, "validation": { "address": "no_match", "date_of_birth": "no_match", "full_name": "no_match" } } ] } ``` ## Returned data The exact fields surfaced in `source_data` depend on what the registry returns. The generated example for `esp_dni` currently documents this normalized shape: * `address_match_score` * `date_of_birth` * `first_name` * `full_name` * `identification_number` * `last_name` * `name_match_score` ## Pricing & SLAs Spain - DNI/NIE verification queries are billed only when Didit receives a conclusive result from the validation source. * **Per-call price:** \$1.26 USD. * **Billing:** per successful query. You are not charged when the registry is unreachable, when required fields are missing, or when the request is rejected before reaching the source. * **Latency:** typical p95 \< 2 s. * **Availability:** 99.9% per quarter on Didit's side; downstream source availability varies by country and dataset. ## Continue reading * [Spain Database Validation overview](/api-reference/database-validation/spain) * [Database Validation overview](/core-technology/database-validation/overview) * [Outcome Codes](/core-technology/database-validation/database-validation-outcome-codes) # Sweden National ID Source: https://docs.didit.me/api-reference/database-validation/sweden/national-id POST /v3/database-validation/ Verifies input data against the Swedish Police Authority service. Authoritative real-time identity lookup for Sweden. Real-time lookup, pay-per-call.
Verifies input data against the Swedish Police Authority service. Didit exposes this service through `POST /v3/database-validation/` so you can verify the submitted data against the authoritative source and receive normalized match results. ## Coverage * **Coverage:** \~ 100% * **Country:** Sweden * **Service ID:** `swe_national_id` * **Data domain:** Identity * **Category:** NationalIDRegistry ## Inputs | Field | Required | Example | | --------------------- | -------: | ------------------- | | `first_name` | Yes | `John` | | `last_name` | Yes | `Doe` | | `date_of_birth` | Yes | `1990-01-01` | | `national_id` | Yes | `11111111` | | `address.street_1` | No | `123 Sample Street` | | `address.street_2` | No | `Unit 4` | | `address.city` | No | `Sample City` | | `address.region` | No | `Sample State` | | `address.postal_code` | No | `10001` | | `vendor_data` | No | `user-1234` | * **Required inputs:** `first_name`, `last_name`, `date_of_birth`, `national_id` * **Optional inputs:** `address.street_1`, `address.street_2`, `address.city`, `address.region`, `address.postal_code`, `vendor_data` * **Consent:** Not required * **Workflow availability:** Available in workflow * **Coverage:** \~ 100% * **Price:** \$0.35 per successful query Not every document this service accepts carries the identifier it queries by. When the identifier is not extracted from the document the check is recorded as **not applicable** - no database is queried and you are not charged - which for some countries is a large share of real users. To cover them, also collect the identifier from a Questionnaire answer, a Document AI extraction field, or a value you send when you create the session, and map it on the Database Validation step. ## Body parameters ISO 3166-1 alpha-3 country code for this database service. Example: `SWE` Array containing this service ID. Pinning the service keeps the request scoped to this exact database. Example: `swe_national_id` Given name to validate. Example: `John` Family name to validate. Example: `Doe` Date of birth in `YYYY-MM-DD` format. Example: `1990-01-01` National identity number for this service. Example: `11111111` Structured residential address object. Use `street_1`, `street_2`, `city`, `region`, `postal_code`, and `country`. A complete legacy address string is still accepted but not recommended. Example: `{"street_1":"123 Sample Street","street_2":"Unit 4","city":"Sample City","region":"Sample State","postal_code":"10001","country":"US"}` Your stable user reference for this person, such as your internal user ID. Didit uses it to link standalone checks to the same end user and reduce duplicate-detection noise. Example: `user-1234` ## Input rules & validation notes * `address` is optional for this service. You can send one complete `address` string and Didit will split it into structured address elements when possible, or you can send the structured fields explicitly. * `national_id` must contain digits only; remove spaces, hyphens, and punctuation before sending the request. * `national_id` must match `(\d{10}|\d{12})`. * For address services, send structured address fields instead of a single `address` string when possible. * `address.street_1` is the street address, including street number and street type. * `address.street_2` is apartment, unit, building, floor, or extra address line. Send it only when you have it. * `address.city` is city, suburb, district, locality, or neighborhood. * `address.region` is state, province, region, or town. * `address.postal_code` is postcode or postal code. * Address-based database services require at least street address and postal code; requests rejected before source lookup are not charged. ## How to call it ```bash cURL theme={null} curl -X POST "https://verification.didit.me/v3/database-validation/" \ -H "x-api-key: YOUR_API_KEY" \ -F "issuing_state=SWE" \ -F "services=swe_national_id" \ -F "vendor_data=user-1234" \ -F "first_name=John" \ -F "last_name=Doe" \ -F "date_of_birth=1990-01-01" \ -F "national_id=11111111" ``` Every successful call returns HTTP `200`. The **`outcome_code`** field tells you what actually happened — distinguishing, for example, a real biometric mismatch (`BIOMETRIC_NO_MATCH`) from a selfie that could not be read (`BIOMETRIC_IMAGE_UNUSABLE`). The `status` shown is the default feature status; your configured [Partial Match / No Match actions](/core-technology/database-validation/database-validation-warnings) can override it. **`MATCH`** — The registry confirmed the identity and every checked field matched. ```json 200 OK — MATCH theme={null} { "request_id": "req_01H…", "status": "Approved", "issuing_state": "SWE", "match_type": "full_match", "validations": [ { "outcome_code": "MATCH", "service_id": "swe_national_id", "service_name": "Sweden National ID", "source_data": { "date_of_birth": "1990-01-01", "first_name": "John", "full_name": "John Doe", "identification_number": "SAMPLE-ID-12345", "last_name": "Doe", "name_match_score": "1.000", "verifications": { "date_of_birth": true, "full_name": true, "identification_number": true } }, "validation": { "date_of_birth": "full_match", "full_name": "full_match", "identification_number": "full_match" } } ] } ``` **`PARTIAL_MATCH`** — The identification number was found but one or more personal fields (usually name or date of birth) did not fully match. ```json 200 OK — PARTIAL_MATCH theme={null} { "request_id": "req_01H…", "status": "In Review", "issuing_state": "SWE", "match_type": "partial_match", "validations": [ { "outcome_code": "PARTIAL_MATCH", "service_id": "swe_national_id", "service_name": "Sweden National ID", "source_data": { "date_of_birth": "1990-01-01", "first_name": "John", "full_name": "John Doe", "identification_number": "SAMPLE-ID-12345", "last_name": "Doe", "name_match_score": "1.000", "verifications": { "date_of_birth": true, "full_name": false, "identification_number": true } }, "validation": { "date_of_birth": "full_match", "full_name": "no_match", "identification_number": "full_match" } } ] } ``` **`NO_MATCH`** — The registry returned no match for the submitted data. ```json 200 OK — NO_MATCH theme={null} { "request_id": "req_01H…", "status": "Declined", "issuing_state": "SWE", "match_type": "no_match", "validations": [ { "outcome_code": "NO_MATCH", "service_id": "swe_national_id", "service_name": "Sweden National ID", "source_data": { "date_of_birth": "NO_MATCH", "full_name": "NO_MATCH", "identification_number": "NO_MATCH" }, "validation": { "date_of_birth": "no_match", "full_name": "no_match", "identification_number": "no_match" } } ] } ``` ## Returned data The exact fields surfaced in `source_data` depend on what the registry returns. The generated example for `swe_national_id` currently documents this normalized shape: * `date_of_birth` * `first_name` * `full_name` * `identification_number` * `last_name` * `name_match_score` ## Pricing & SLAs Sweden National ID queries are billed only when Didit receives a conclusive result from the validation source. * **Per-call price:** \$0.35 USD. * **Billing:** per successful query. You are not charged when the registry is unreachable, when required fields are missing, or when the request is rejected before reaching the source. * **Latency:** typical p95 \< 2 s. * **Availability:** 99.9% per quarter on Didit's side; downstream source availability varies by country and dataset. ## Continue reading * [Sweden Database Validation overview](/api-reference/database-validation/sweden) * [Database Validation overview](/core-technology/database-validation/overview) * [Outcome Codes](/core-technology/database-validation/database-validation-outcome-codes) # Sweden Phone Source: https://docs.didit.me/api-reference/database-validation/sweden/phone POST /v3/database-validation/ Verifies input data to mobile network operators phone data. Authoritative real-time identity lookup for Sweden. Real-time lookup, pay-per-call.
Verifies input data to mobile network operators phone data. Didit exposes this service through `POST /v3/database-validation/` so you can verify the submitted data against the authoritative source and receive normalized match results. ## Coverage * **Coverage:** \~ 100% * **Country:** Sweden * **Service ID:** `swe_phone` * **Data domain:** Telecom * **Category:** Telecom ## Inputs | Field | Required | Example | | --------------------- | -------: | ------------------- | | `first_name` | Yes | `John` | | `last_name` | Yes | `Doe` | | `address.street_1` | Yes | `123 Sample Street` | | `address.postal_code` | Yes | `10001` | | `phone` | Yes | `+15550101000` | | `date_of_birth` | No | `1990-01-01` | | `national_id` | No | `SAMPLE-NID-12345` | | `address.street_2` | No | `Unit 4` | | `address.city` | No | `Sample City` | | `address.region` | No | `Sample State` | | `vendor_data` | No | `user-1234` | * **Required inputs:** `first_name`, `last_name`, `address.street_1`, `address.postal_code`, `phone` * **Optional inputs:** `date_of_birth`, `national_id`, `address.street_2`, `address.city`, `address.region`, `vendor_data` * **Consent:** Not required * **Workflow availability:** Available in workflow * **Coverage:** \~ 100% * **Price:** \$0.35 per successful query ## Body parameters ISO 3166-1 alpha-3 country code for this database service. Example: `SWE` Array containing this service ID. Pinning the service keeps the request scoped to this exact database. Example: `swe_phone` Given name to validate. Example: `John` Family name to validate. Example: `Doe` Structured residential address object. Use `street_1`, `street_2`, `city`, `region`, `postal_code`, and `country`. A complete legacy address string is still accepted but not recommended. Example: `{"street_1":"123 Sample Street","street_2":"Unit 4","city":"Sample City","region":"Sample State","postal_code":"10001","country":"US"}` Phone number in international format. Example: `+15550101000` Date of birth in `YYYY-MM-DD` format. Example: `1990-01-01` National identity number for this service. Example: `SAMPLE-NID-12345` Your stable user reference for this person, such as your internal user ID. Didit uses it to link standalone checks to the same end user and reduce duplicate-detection noise. Example: `user-1234` ## Input rules & validation notes * For address services, send structured address fields instead of a single `address` string when possible. * `address.street_1` is the street address, including street number and street type. * `address.street_2` is apartment, unit, building, floor, or extra address line. Send it only when you have it. * `address.city` is city, suburb, district, locality, or neighborhood. * `address.region` is state, province, region, or town. * `address.postal_code` is postcode or postal code. * Address-based database services require at least street address and postal code; requests rejected before source lookup are not charged. ## How to call it ```bash cURL theme={null} curl -X POST "https://verification.didit.me/v3/database-validation/" \ -H "x-api-key: YOUR_API_KEY" \ -F "issuing_state=SWE" \ -F "services=swe_phone" \ -F "vendor_data=user-1234" \ -F "first_name=John" \ -F "last_name=Doe" \ -F 'address={"street_1":"123 Sample Street","street_2":"Unit 4","city":"Sample City","region":"Sample State","postal_code":"10001","country":"US"}' \ -F "phone=+15550101000" ``` Every successful call returns HTTP `200`. The **`outcome_code`** field tells you what actually happened — distinguishing, for example, a real biometric mismatch (`BIOMETRIC_NO_MATCH`) from a selfie that could not be read (`BIOMETRIC_IMAGE_UNUSABLE`). The `status` shown is the default feature status; your configured [Partial Match / No Match actions](/core-technology/database-validation/database-validation-warnings) can override it. **`MATCH`** — The registry confirmed the identity and every checked field matched. ```json 200 OK — MATCH theme={null} { "request_id": "req_01H…", "status": "Approved", "issuing_state": "SWE", "match_type": "full_match", "validations": [ { "outcome_code": "MATCH", "service_id": "swe_phone", "service_name": "Sweden Phone", "source_data": { "address": "123 Sample Street", "date_of_birth": "1990-01-01", "first_name": "John", "identification_number": "SAMPLE-ID-12345", "last_name": "Doe" }, "validation": { "address": "full_match", "full_name": "full_match" } } ] } ``` **`PARTIAL_MATCH`** — The identification number was found but one or more personal fields (usually name or date of birth) did not fully match. ```json 200 OK — PARTIAL_MATCH theme={null} { "request_id": "req_01H…", "status": "In Review", "issuing_state": "SWE", "match_type": "partial_match", "validations": [ { "outcome_code": "PARTIAL_MATCH", "service_id": "swe_phone", "service_name": "Sweden Phone", "source_data": { "address": "123 Sample Street", "date_of_birth": "1990-01-01", "first_name": "John", "identification_number": "SAMPLE-ID-12345", "last_name": "Doe" }, "validation": { "address": "full_match", "full_name": "no_match" } } ] } ``` **`NO_MATCH`** — The registry returned no match for the submitted data. ```json 200 OK — NO_MATCH theme={null} { "request_id": "req_01H…", "status": "Declined", "issuing_state": "SWE", "match_type": "no_match", "validations": [ { "outcome_code": "NO_MATCH", "service_id": "swe_phone", "service_name": "Sweden Phone", "source_data": { "address": "NO_MATCH", "full_name": "NO_MATCH" }, "validation": { "address": "no_match", "full_name": "no_match" } } ] } ``` ## Returned data The exact fields surfaced in `source_data` depend on what the registry returns. The generated example for `swe_phone` currently documents this normalized shape: * `address` * `date_of_birth` * `first_name` * `identification_number` * `last_name` ## Pricing & SLAs Sweden Phone queries are billed only when Didit receives a conclusive result from the validation source. * **Per-call price:** \$0.35 USD. * **Billing:** per successful query. You are not charged when the registry is unreachable, when required fields are missing, or when the request is rejected before reaching the source. * **Latency:** typical p95 \< 2 s. * **Availability:** 99.9% per quarter on Didit's side; downstream source availability varies by country and dataset. ## Continue reading * [Sweden Database Validation overview](/api-reference/database-validation/sweden) * [Database Validation overview](/core-technology/database-validation/overview) * [Outcome Codes](/core-technology/database-validation/database-validation-outcome-codes) # Switzerland Credit Bureau Source: https://docs.didit.me/api-reference/database-validation/switzerland/credit-bureau POST /v3/database-validation/ Credit Header data obtained from the Credit Bureau in Switzerland. Authoritative real-time identity lookup for Switzerland. Real-time lookup, pay-per-call.
Credit Header data obtained from the Credit Bureau in Switzerland. Didit exposes this service through `POST /v3/database-validation/` so you can verify the submitted data against the authoritative source and receive normalized match results. ## Coverage * **Coverage:** \~ 85% * **Country:** Switzerland * **Service ID:** `che_credit_bureau` * **Data domain:** Financial * **Category:** CreditBureau ## Inputs | Field | Required | Example | | --------------------- | -------: | ------------------- | | `first_name` | Yes | `John` | | `last_name` | Yes | `Doe` | | `date_of_birth` | Yes | `1990-01-01` | | `address.street_1` | Yes | `123 Sample Street` | | `address.postal_code` | Yes | `10001` | | `address.street_2` | No | `Unit 4` | | `address.city` | No | `Sample City` | | `address.region` | No | `Sample State` | | `vendor_data` | No | `user-1234` | * **Required inputs:** `first_name`, `last_name`, `date_of_birth`, `address.street_1`, `address.postal_code` * **Optional inputs:** `address.street_2`, `address.city`, `address.region`, `vendor_data` * **Consent:** Required * **Workflow availability:** Available in workflow * **Coverage:** \~ 85% * **Price:** \$2.00 per successful query ## Body parameters ISO 3166-1 alpha-3 country code for this database service. Example: `CHE` Array containing this service ID. Pinning the service keeps the request scoped to this exact database. Example: `che_credit_bureau` Explicit end-user consent for this service. Example: `true` Given name to validate. Example: `John` Family name to validate. Example: `Doe` Date of birth in `YYYY-MM-DD` format. Example: `1990-01-01` Structured residential address object. Use `street_1`, `street_2`, `city`, `region`, `postal_code`, and `country`. A complete legacy address string is still accepted but not recommended. Example: `{"street_1":"123 Sample Street","street_2":"Unit 4","city":"Sample City","region":"Sample State","postal_code":"10001","country":"US"}` Your stable user reference for this person, such as your internal user ID. Didit uses it to link standalone checks to the same end user and reduce duplicate-detection noise. Example: `user-1234` ## Input rules & validation notes * For address services, send structured address fields instead of a single `address` string when possible. * `address.street_1` is the street address, including street number and street type. * `address.street_2` is apartment, unit, building, floor, or extra address line. Send it only when you have it. * `address.city` is city, suburb, district, locality, or neighborhood. * `address.region` is state, province, region, or town. * `address.postal_code` is postcode or postal code. * Address-based database services require at least street address and postal code; requests rejected before source lookup are not charged. ## How to call it ```bash cURL theme={null} curl -X POST "https://verification.didit.me/v3/database-validation/" \ -H "x-api-key: YOUR_API_KEY" \ -F "issuing_state=CHE" \ -F "services=che_credit_bureau" \ -F "vendor_data=user-1234" \ -F "consent=true" \ -F "first_name=John" \ -F "last_name=Doe" \ -F "date_of_birth=1990-01-01" \ -F 'address={"street_1":"123 Sample Street","street_2":"Unit 4","city":"Sample City","region":"Sample State","postal_code":"10001","country":"US"}' ``` Every successful call returns HTTP `200`. The **`outcome_code`** field tells you what actually happened — distinguishing, for example, a real biometric mismatch (`BIOMETRIC_NO_MATCH`) from a selfie that could not be read (`BIOMETRIC_IMAGE_UNUSABLE`). The `status` shown is the default feature status; your configured [Partial Match / No Match actions](/core-technology/database-validation/database-validation-warnings) can override it. **`MATCH`** — The registry confirmed the identity and every checked field matched. ```json 200 OK — MATCH theme={null} { "request_id": "req_01H…", "status": "Approved", "issuing_state": "CHE", "match_type": "full_match", "validations": [ { "outcome_code": "MATCH", "service_id": "che_credit_bureau", "service_name": "Switzerland Credit Bureau", "source_data": { "address": "123 Sample Street", "date_of_birth": "1990-01-01", "first_name": "John", "last_name": "Doe" }, "validation": { "address": "full_match", "date_of_birth": "full_match", "full_name": "full_match" } } ] } ``` **`PARTIAL_MATCH`** — The identification number was found but one or more personal fields (usually name or date of birth) did not fully match. ```json 200 OK — PARTIAL_MATCH theme={null} { "request_id": "req_01H…", "status": "In Review", "issuing_state": "CHE", "match_type": "partial_match", "validations": [ { "outcome_code": "PARTIAL_MATCH", "service_id": "che_credit_bureau", "service_name": "Switzerland Credit Bureau", "source_data": { "address": "123 Sample Street", "date_of_birth": "1990-01-01", "first_name": "John", "last_name": "Doe" }, "validation": { "address": "full_match", "date_of_birth": "full_match", "full_name": "no_match" } } ] } ``` **`NO_MATCH`** — The registry returned no match for the submitted data. ```json 200 OK — NO_MATCH theme={null} { "request_id": "req_01H…", "status": "Declined", "issuing_state": "CHE", "match_type": "no_match", "validations": [ { "outcome_code": "NO_MATCH", "service_id": "che_credit_bureau", "service_name": "Switzerland Credit Bureau", "source_data": { "address": "NO_MATCH", "date_of_birth": "NO_MATCH", "full_name": "NO_MATCH" }, "validation": { "address": "no_match", "date_of_birth": "no_match", "full_name": "no_match" } } ] } ``` ## Returned data The exact fields surfaced in `source_data` depend on what the registry returns. The generated example for `che_credit_bureau` currently documents this normalized shape: * `address` * `date_of_birth` * `first_name` * `last_name` ## Pricing & SLAs Switzerland Credit Bureau queries are billed only when Didit receives a conclusive result from the validation source. * **Per-call price:** \$2.00 USD. * **Billing:** per successful query. You are not charged when the registry is unreachable, when required fields are missing, or when the request is rejected before reaching the source. * **Latency:** typical p95 \< 2 s. * **Availability:** 99.9% per quarter on Didit's side; downstream source availability varies by country and dataset. ## Continue reading * [Switzerland Database Validation overview](/api-reference/database-validation/switzerland) * [Database Validation overview](/core-technology/database-validation/overview) * [Outcome Codes](/core-technology/database-validation/database-validation-outcome-codes) # Thailand National ID Source: https://docs.didit.me/api-reference/database-validation/thailand/national-id POST /v3/database-validation/ Verifies input data against government agency sourced National ID. Authoritative real-time identity lookup for Thailand. Real-time lookup, pay-per-call.
Verifies input data against government agency sourced National ID. Didit exposes this service through `POST /v3/database-validation/` so you can verify the submitted data against the authoritative source and receive normalized match results. ## Coverage * **Coverage:** \~ 90% * **Country:** Thailand * **Service ID:** `tha_national_id` * **Data domain:** Identity * **Category:** NationalIDRegistry ## Inputs | Field | Required | Example | | --------------------- | -------: | ------------------- | | `first_name` | Yes | `John` | | `last_name` | Yes | `Doe` | | `date_of_birth` | Yes | `1990-01-01` | | `national_id` | Yes | `1111111111111` | | `address.street_1` | No | `123 Sample Street` | | `address.street_2` | No | `Unit 4` | | `address.city` | No | `Sample City` | | `address.region` | No | `Sample State` | | `address.postal_code` | No | `10001` | | `vendor_data` | No | `user-1234` | * **Required inputs:** `first_name`, `last_name`, `date_of_birth`, `national_id` * **Optional inputs:** `address.street_1`, `address.street_2`, `address.city`, `address.region`, `address.postal_code`, `vendor_data` * **Consent:** Required * **Workflow availability:** Available in workflow * **Coverage:** \~ 90% * **Price:** \$0.35 per successful query ## Body parameters ISO 3166-1 alpha-3 country code for this database service. Example: `THA` Array containing this service ID. Pinning the service keeps the request scoped to this exact database. Example: `tha_national_id` Explicit end-user consent for this service. Example: `true` Given name to validate. Example: `John` Family name to validate. Example: `Doe` Date of birth in `YYYY-MM-DD` format. Example: `1990-01-01` National identity number for this service. Example: `1111111111111` Structured residential address object. Use `street_1`, `street_2`, `city`, `region`, `postal_code`, and `country`. A complete legacy address string is still accepted but not recommended. Example: `{"street_1":"123 Sample Street","street_2":"Unit 4","city":"Sample City","region":"Sample State","postal_code":"10001","country":"US"}` Your stable user reference for this person, such as your internal user ID. Didit uses it to link standalone checks to the same end user and reduce duplicate-detection noise. Example: `user-1234` ## Input rules & validation notes * `address` is optional for this service. You can send one complete `address` string and Didit will split it into structured address elements when possible, or you can send the structured fields explicitly. * Thai national ID number: 13 digits whose last digit is the mod-11 check digit (weights 13 to 2 over the first twelve digits). * `national_id` must contain digits only; remove spaces, hyphens, and punctuation before sending the request. * `national_id` must be exactly 13 characters long. * The final Thai national ID check digit (mod 11) is validated; a number that fails the check is refused before the lookup and is not charged. * For address services, send structured address fields instead of a single `address` string when possible. * `address.street_1` is the street address, including street number and street type. * `address.street_2` is apartment, unit, building, floor, or extra address line. Send it only when you have it. * `address.city` is city, suburb, district, locality, or neighborhood. * `address.region` is state, province, region, or town. * `address.postal_code` is postcode or postal code. * Address-based database services require at least street address and postal code; requests rejected before source lookup are not charged. ## How to call it ```bash cURL theme={null} curl -X POST "https://verification.didit.me/v3/database-validation/" \ -H "x-api-key: YOUR_API_KEY" \ -F "issuing_state=THA" \ -F "services=tha_national_id" \ -F "vendor_data=user-1234" \ -F "consent=true" \ -F "first_name=John" \ -F "last_name=Doe" \ -F "date_of_birth=1990-01-01" \ -F "national_id=1111111111111" ``` Every successful call returns HTTP `200`. The **`outcome_code`** field tells you what actually happened — distinguishing, for example, a real biometric mismatch (`BIOMETRIC_NO_MATCH`) from a selfie that could not be read (`BIOMETRIC_IMAGE_UNUSABLE`). The `status` shown is the default feature status; your configured [Partial Match / No Match actions](/core-technology/database-validation/database-validation-warnings) can override it. **`MATCH`** — The registry confirmed the identity and every checked field matched. ```json 200 OK — MATCH theme={null} { "request_id": "req_01H…", "status": "Approved", "issuing_state": "THA", "match_type": "full_match", "validations": [ { "outcome_code": "MATCH", "service_id": "tha_national_id", "service_name": "Thailand National ID", "source_data": { "address_match_score": "1.000", "date_of_birth": "1990-01-01", "identification_number": "SAMPLE-ID-12345", "name_match_score": "1.000", "verifications": { "date_of_birth": true, "full_name": true, "identification_number": true } }, "validation": { "date_of_birth": "full_match", "full_name": "full_match", "identification_number": "full_match" } } ] } ``` **`PARTIAL_MATCH`** — The identification number was found but one or more personal fields (usually name or date of birth) did not fully match. ```json 200 OK — PARTIAL_MATCH theme={null} { "request_id": "req_01H…", "status": "In Review", "issuing_state": "THA", "match_type": "partial_match", "validations": [ { "outcome_code": "PARTIAL_MATCH", "service_id": "tha_national_id", "service_name": "Thailand National ID", "source_data": { "address_match_score": "1.000", "date_of_birth": "1990-01-01", "identification_number": "SAMPLE-ID-12345", "name_match_score": "1.000", "verifications": { "date_of_birth": true, "full_name": false, "identification_number": true } }, "validation": { "date_of_birth": "full_match", "full_name": "no_match", "identification_number": "full_match" } } ] } ``` **`NO_MATCH`** — The registry returned no match for the submitted data. ```json 200 OK — NO_MATCH theme={null} { "request_id": "req_01H…", "status": "Declined", "issuing_state": "THA", "match_type": "no_match", "validations": [ { "outcome_code": "NO_MATCH", "service_id": "tha_national_id", "service_name": "Thailand National ID", "source_data": { "date_of_birth": "NO_MATCH", "full_name": "NO_MATCH", "identification_number": "NO_MATCH" }, "validation": { "date_of_birth": "no_match", "full_name": "no_match", "identification_number": "no_match" } } ] } ``` ## Returned data The exact fields surfaced in `source_data` depend on what the registry returns. The generated example for `tha_national_id` currently documents this normalized shape: * `address_match_score` * `date_of_birth` * `identification_number` * `name_match_score` ## Pricing & SLAs Thailand National ID queries are billed only when Didit receives a conclusive result from the validation source. * **Per-call price:** \$0.35 USD. * **Billing:** per successful query. You are not charged when the registry is unreachable, when required fields are missing, or when the request is rejected before reaching the source. * **Latency:** typical p95 \< 2 s. * **Availability:** 99.9% per quarter on Didit's side; downstream source availability varies by country and dataset. ## Continue reading * [Thailand Database Validation overview](/api-reference/database-validation/thailand) * [Database Validation overview](/core-technology/database-validation/overview) * [Outcome Codes](/core-technology/database-validation/database-validation-outcome-codes) # United Kingdom Credit Bureau Source: https://docs.didit.me/api-reference/database-validation/united-kingdom/credit-bureau POST /v3/database-validation/ Verifies input data against Credit Header data obtained from a Credit Bureau in the United Kingdom. Authoritative real-time identity lookup for United Kingdom. Real-time lookup, pay-per-call.
Verifies input data against Credit Header data obtained from a Credit Bureau in the United Kingdom. Didit exposes this service through `POST /v3/database-validation/` so you can verify the submitted data against the authoritative source and receive normalized match results. ## Coverage * **Coverage:** \~ 85% * **Country:** United Kingdom * **Service ID:** `gbr_kingdom_credit_bureau` * **Data domain:** Financial * **Category:** CreditBureau ## Inputs | Field | Required | Example | | --------------------- | -------: | ------------------- | | `first_name` | Yes | `John` | | `last_name` | Yes | `Doe` | | `date_of_birth` | Yes | `1990-01-01` | | `address.street_1` | Yes | `123 Sample Street` | | `address.postal_code` | Yes | `10001` | | `address.street_2` | No | `Unit 4` | | `address.city` | No | `Sample City` | | `address.region` | No | `Sample State` | | `vendor_data` | No | `user-1234` | * **Required inputs:** `first_name`, `last_name`, `date_of_birth`, `address.street_1`, `address.postal_code` * **Optional inputs:** `address.street_2`, `address.city`, `address.region`, `vendor_data` * **Consent:** Required * **Workflow availability:** Available in workflow * **Coverage:** \~ 85% * **Price:** \$0.90 per successful query ## Body parameters ISO 3166-1 alpha-3 country code for this database service. Example: `GBR` Array containing this service ID. Pinning the service keeps the request scoped to this exact database. Example: `gbr_kingdom_credit_bureau` Explicit end-user consent for this service. Example: `true` Given name to validate. Example: `John` Family name to validate. Example: `Doe` Date of birth in `YYYY-MM-DD` format. Example: `1990-01-01` Structured residential address object. Use `street_1`, `street_2`, `city`, `region`, `postal_code`, and `country`. A complete legacy address string is still accepted but not recommended. Example: `{"street_1":"123 Sample Street","street_2":"Unit 4","city":"Sample City","region":"Sample State","postal_code":"10001","country":"US"}` Your stable user reference for this person, such as your internal user ID. Didit uses it to link standalone checks to the same end user and reduce duplicate-detection noise. Example: `user-1234` ## Input rules & validation notes * For address services, send structured address fields instead of a single `address` string when possible. * `address.street_1` is the street address, including street number and street type. * `address.street_2` is apartment, unit, building, floor, or extra address line. Send it only when you have it. * `address.city` is city, suburb, district, locality, or neighborhood. * `address.region` is state, province, region, or town. * `address.postal_code` is postcode or postal code. * Address-based database services require at least street address and postal code; requests rejected before source lookup are not charged. ## How to call it ```bash cURL theme={null} curl -X POST "https://verification.didit.me/v3/database-validation/" \ -H "x-api-key: YOUR_API_KEY" \ -F "issuing_state=GBR" \ -F "services=gbr_kingdom_credit_bureau" \ -F "vendor_data=user-1234" \ -F "consent=true" \ -F "first_name=John" \ -F "last_name=Doe" \ -F "date_of_birth=1990-01-01" \ -F 'address={"street_1":"123 Sample Street","street_2":"Unit 4","city":"Sample City","region":"Sample State","postal_code":"10001","country":"US"}' ``` Every successful call returns HTTP `200`. The **`outcome_code`** field tells you what actually happened — distinguishing, for example, a real biometric mismatch (`BIOMETRIC_NO_MATCH`) from a selfie that could not be read (`BIOMETRIC_IMAGE_UNUSABLE`). The `status` shown is the default feature status; your configured [Partial Match / No Match actions](/core-technology/database-validation/database-validation-warnings) can override it. **`MATCH`** — The registry confirmed the identity and every checked field matched. ```json 200 OK — MATCH theme={null} { "request_id": "req_01H…", "status": "Approved", "issuing_state": "GBR", "match_type": "full_match", "validations": [ { "outcome_code": "MATCH", "service_id": "gbr_kingdom_credit_bureau", "service_name": "United Kingdom Credit Bureau", "source_data": { "address": "123 Sample Street", "date_of_birth": "1990-01-01", "first_name": "John", "last_name": "Doe" }, "validation": { "address": "full_match", "date_of_birth": "full_match", "full_name": "full_match" } } ] } ``` **`PARTIAL_MATCH`** — The identification number was found but one or more personal fields (usually name or date of birth) did not fully match. ```json 200 OK — PARTIAL_MATCH theme={null} { "request_id": "req_01H…", "status": "In Review", "issuing_state": "GBR", "match_type": "partial_match", "validations": [ { "outcome_code": "PARTIAL_MATCH", "service_id": "gbr_kingdom_credit_bureau", "service_name": "United Kingdom Credit Bureau", "source_data": { "address": "123 Sample Street", "date_of_birth": "1990-01-01", "first_name": "John", "last_name": "Doe" }, "validation": { "address": "full_match", "date_of_birth": "full_match", "full_name": "no_match" } } ] } ``` **`NO_MATCH`** — The registry returned no match for the submitted data. ```json 200 OK — NO_MATCH theme={null} { "request_id": "req_01H…", "status": "Declined", "issuing_state": "GBR", "match_type": "no_match", "validations": [ { "outcome_code": "NO_MATCH", "service_id": "gbr_kingdom_credit_bureau", "service_name": "United Kingdom Credit Bureau", "source_data": { "address": "NO_MATCH", "date_of_birth": "NO_MATCH", "full_name": "NO_MATCH" }, "validation": { "address": "no_match", "date_of_birth": "no_match", "full_name": "no_match" } } ] } ``` ## Returned data The exact fields surfaced in `source_data` depend on what the registry returns. The generated example for `gbr_kingdom_credit_bureau` currently documents this normalized shape: * `address` * `date_of_birth` * `first_name` * `last_name` ## Pricing & SLAs United Kingdom Credit Bureau queries are billed only when Didit receives a conclusive result from the validation source. * **Per-call price:** \$0.90 USD. * **Billing:** per successful query. You are not charged when the registry is unreachable, when required fields are missing, or when the request is rejected before reaching the source. * **Latency:** typical p95 \< 2 s. * **Availability:** 99.9% per quarter on Didit's side; downstream source availability varies by country and dataset. ## Continue reading * [United Kingdom Database Validation overview](/api-reference/database-validation/united-kingdom) * [Database Validation overview](/core-technology/database-validation/overview) * [Outcome Codes](/core-technology/database-validation/database-validation-outcome-codes) # United Kingdom Financial Services Source: https://docs.didit.me/api-reference/database-validation/united-kingdom/financial-services POST /v3/database-validation/ Aggregated service of government and public records, background records, and other services. Authoritative real-time identity lookup for United Kingdom. Real-time lookup, pay-per-call.
Aggregated service of government and public records, background records, and other services. Didit exposes this service through `POST /v3/database-validation/` so you can verify the submitted data against the authoritative source and receive normalized match results. ## Coverage * **Coverage:** \~ 85% * **Country:** United Kingdom * **Service ID:** `gbr_kingdom_financial_services` * **Data domain:** Financial * **Category:** FinancialServices ## Inputs | Field | Required | Example | | --------------------- | -------: | ------------------- | | `first_name` | Yes | `John` | | `last_name` | Yes | `Doe` | | `date_of_birth` | Yes | `1990-01-01` | | `address.street_1` | Yes | `123 Sample Street` | | `address.postal_code` | Yes | `10001` | | `phone` | No | `+15550101000` | | `address.street_2` | No | `Unit 4` | | `address.city` | No | `Sample City` | | `address.region` | No | `Sample State` | | `vendor_data` | No | `user-1234` | * **Required inputs:** `first_name`, `last_name`, `date_of_birth`, `address.street_1`, `address.postal_code` * **Optional inputs:** `phone`, `address.street_2`, `address.city`, `address.region`, `vendor_data` * **Consent:** Not required * **Workflow availability:** Available in workflow * **Coverage:** \~ 85% * **Price:** \$0.95 per successful query ## Body parameters ISO 3166-1 alpha-3 country code for this database service. Example: `GBR` Array containing this service ID. Pinning the service keeps the request scoped to this exact database. Example: `gbr_kingdom_financial_services` Given name to validate. Example: `John` Family name to validate. Example: `Doe` Date of birth in `YYYY-MM-DD` format. Example: `1990-01-01` Structured residential address object. Use `street_1`, `street_2`, `city`, `region`, `postal_code`, and `country`. A complete legacy address string is still accepted but not recommended. Example: `{"street_1":"123 Sample Street","street_2":"Unit 4","city":"Sample City","region":"Sample State","postal_code":"10001","country":"US"}` Phone number in international format. Example: `+15550101000` Your stable user reference for this person, such as your internal user ID. Didit uses it to link standalone checks to the same end user and reduce duplicate-detection noise. Example: `user-1234` ## Input rules & validation notes * For address services, send structured address fields instead of a single `address` string when possible. * `address.street_1` is the street address, including street number and street type. * `address.street_2` is apartment, unit, building, floor, or extra address line. Send it only when you have it. * `address.city` is city, suburb, district, locality, or neighborhood. * `address.region` is state, province, region, or town. * `address.postal_code` is postcode or postal code. * Address-based database services require at least street address and postal code; requests rejected before source lookup are not charged. ## How to call it ```bash cURL theme={null} curl -X POST "https://verification.didit.me/v3/database-validation/" \ -H "x-api-key: YOUR_API_KEY" \ -F "issuing_state=GBR" \ -F "services=gbr_kingdom_financial_services" \ -F "vendor_data=user-1234" \ -F "first_name=John" \ -F "last_name=Doe" \ -F "date_of_birth=1990-01-01" \ -F 'address={"street_1":"123 Sample Street","street_2":"Unit 4","city":"Sample City","region":"Sample State","postal_code":"10001","country":"US"}' ``` Every successful call returns HTTP `200`. The **`outcome_code`** field tells you what actually happened — distinguishing, for example, a real biometric mismatch (`BIOMETRIC_NO_MATCH`) from a selfie that could not be read (`BIOMETRIC_IMAGE_UNUSABLE`). The `status` shown is the default feature status; your configured [Partial Match / No Match actions](/core-technology/database-validation/database-validation-warnings) can override it. **`MATCH`** — The registry confirmed the identity and every checked field matched. ```json 200 OK — MATCH theme={null} { "request_id": "req_01H…", "status": "Approved", "issuing_state": "GBR", "match_type": "full_match", "validations": [ { "outcome_code": "MATCH", "service_id": "gbr_kingdom_financial_services", "service_name": "United Kingdom Financial Services", "source_data": { "address": "123 Sample Street", "date_of_birth": "1990-01-01", "first_name": "John", "last_name": "Doe" }, "validation": { "address": "full_match", "date_of_birth": "full_match", "full_name": "full_match" } } ] } ``` **`PARTIAL_MATCH`** — The identification number was found but one or more personal fields (usually name or date of birth) did not fully match. ```json 200 OK — PARTIAL_MATCH theme={null} { "request_id": "req_01H…", "status": "In Review", "issuing_state": "GBR", "match_type": "partial_match", "validations": [ { "outcome_code": "PARTIAL_MATCH", "service_id": "gbr_kingdom_financial_services", "service_name": "United Kingdom Financial Services", "source_data": { "address": "123 Sample Street", "date_of_birth": "1990-01-01", "first_name": "John", "last_name": "Doe" }, "validation": { "address": "full_match", "date_of_birth": "full_match", "full_name": "no_match" } } ] } ``` **`NO_MATCH`** — The registry returned no match for the submitted data. ```json 200 OK — NO_MATCH theme={null} { "request_id": "req_01H…", "status": "Declined", "issuing_state": "GBR", "match_type": "no_match", "validations": [ { "outcome_code": "NO_MATCH", "service_id": "gbr_kingdom_financial_services", "service_name": "United Kingdom Financial Services", "source_data": { "address": "NO_MATCH", "date_of_birth": "NO_MATCH", "full_name": "NO_MATCH" }, "validation": { "address": "no_match", "date_of_birth": "no_match", "full_name": "no_match" } } ] } ``` ## Returned data The exact fields surfaced in `source_data` depend on what the registry returns. The generated example for `gbr_kingdom_financial_services` currently documents this normalized shape: * `address` * `date_of_birth` * `first_name` * `last_name` ## Pricing & SLAs United Kingdom Financial Services queries are billed only when Didit receives a conclusive result from the validation source. * **Per-call price:** \$0.95 USD. * **Billing:** per successful query. You are not charged when the registry is unreachable, when required fields are missing, or when the request is rejected before reaching the source. * **Latency:** typical p95 \< 2 s. * **Availability:** 99.9% per quarter on Didit's side; downstream source availability varies by country and dataset. ## Continue reading * [United Kingdom Database Validation overview](/api-reference/database-validation/united-kingdom) * [Database Validation overview](/core-technology/database-validation/overview) * [Outcome Codes](/core-technology/database-validation/database-validation-outcome-codes) # United Kingdom Phone 2 Source: https://docs.didit.me/api-reference/database-validation/united-kingdom/phone-2 POST /v3/database-validation/ Verifies input data to mobile network operators phone data. Authoritative real-time identity lookup for United Kingdom. Real-time lookup, pay-per-call.
Verifies input data to mobile network operators phone data. Didit exposes this service through `POST /v3/database-validation/` so you can verify the submitted data against the authoritative source and receive normalized match results. ## Coverage * **Coverage:** > 75% * **Country:** United Kingdom * **Service ID:** `gbr_kingdom_phone_2` * **Data domain:** Telecom * **Category:** Telecom ## Inputs | Field | Required | Example | | --------------------- | -------: | ------------------- | | `first_name` | Yes | `John` | | `last_name` | Yes | `Doe` | | `address.street_1` | Yes | `123 Sample Street` | | `address.postal_code` | Yes | `10001` | | `phone` | Yes | `+15550101000` | | `date_of_birth` | No | `1990-01-01` | | `address.street_2` | No | `Unit 4` | | `address.city` | No | `Sample City` | | `address.region` | No | `Sample State` | | `vendor_data` | No | `user-1234` | * **Required inputs:** `first_name`, `last_name`, `address.street_1`, `address.postal_code`, `phone` * **Optional inputs:** `date_of_birth`, `address.street_2`, `address.city`, `address.region`, `vendor_data` * **Consent:** Not required * **Workflow availability:** Available in workflow * **Coverage:** > 75% * **Price:** \$0.96 per successful query ## Body parameters ISO 3166-1 alpha-3 country code for this database service. Example: `GBR` Array containing this service ID. Pinning the service keeps the request scoped to this exact database. Example: `gbr_kingdom_phone_2` Given name to validate. Example: `John` Family name to validate. Example: `Doe` Structured residential address object. Use `street_1`, `street_2`, `city`, `region`, `postal_code`, and `country`. A complete legacy address string is still accepted but not recommended. Example: `{"street_1":"123 Sample Street","street_2":"Unit 4","city":"Sample City","region":"Sample State","postal_code":"10001","country":"US"}` Phone number in international format. Example: `+15550101000` Date of birth in `YYYY-MM-DD` format. Example: `1990-01-01` Your stable user reference for this person, such as your internal user ID. Didit uses it to link standalone checks to the same end user and reduce duplicate-detection noise. Example: `user-1234` ## Input rules & validation notes * For address services, send structured address fields instead of a single `address` string when possible. * `address.street_1` is the street address, including street number and street type. * `address.street_2` is apartment, unit, building, floor, or extra address line. Send it only when you have it. * `address.city` is city, suburb, district, locality, or neighborhood. * `address.region` is state, province, region, or town. * `address.postal_code` is postcode or postal code. * Address-based database services require at least street address and postal code; requests rejected before source lookup are not charged. ## How to call it ```bash cURL theme={null} curl -X POST "https://verification.didit.me/v3/database-validation/" \ -H "x-api-key: YOUR_API_KEY" \ -F "issuing_state=GBR" \ -F "services=gbr_kingdom_phone_2" \ -F "vendor_data=user-1234" \ -F "first_name=John" \ -F "last_name=Doe" \ -F 'address={"street_1":"123 Sample Street","street_2":"Unit 4","city":"Sample City","region":"Sample State","postal_code":"10001","country":"US"}' \ -F "phone=+15550101000" ``` Every successful call returns HTTP `200`. The **`outcome_code`** field tells you what actually happened — distinguishing, for example, a real biometric mismatch (`BIOMETRIC_NO_MATCH`) from a selfie that could not be read (`BIOMETRIC_IMAGE_UNUSABLE`). The `status` shown is the default feature status; your configured [Partial Match / No Match actions](/core-technology/database-validation/database-validation-warnings) can override it. **`MATCH`** — The registry confirmed the identity and every checked field matched. ```json 200 OK — MATCH theme={null} { "request_id": "req_01H…", "status": "Approved", "issuing_state": "GBR", "match_type": "full_match", "validations": [ { "outcome_code": "MATCH", "service_id": "gbr_kingdom_phone_2", "service_name": "United Kingdom Phone 2", "source_data": { "address": "123 Sample Street", "date_of_birth": "1990-01-01", "first_name": "John", "last_name": "Doe" }, "validation": { "address": "full_match", "full_name": "full_match" } } ] } ``` **`PARTIAL_MATCH`** — The identification number was found but one or more personal fields (usually name or date of birth) did not fully match. ```json 200 OK — PARTIAL_MATCH theme={null} { "request_id": "req_01H…", "status": "In Review", "issuing_state": "GBR", "match_type": "partial_match", "validations": [ { "outcome_code": "PARTIAL_MATCH", "service_id": "gbr_kingdom_phone_2", "service_name": "United Kingdom Phone 2", "source_data": { "address": "123 Sample Street", "date_of_birth": "1990-01-01", "first_name": "John", "last_name": "Doe" }, "validation": { "address": "full_match", "full_name": "no_match" } } ] } ``` **`NO_MATCH`** — The registry returned no match for the submitted data. ```json 200 OK — NO_MATCH theme={null} { "request_id": "req_01H…", "status": "Declined", "issuing_state": "GBR", "match_type": "no_match", "validations": [ { "outcome_code": "NO_MATCH", "service_id": "gbr_kingdom_phone_2", "service_name": "United Kingdom Phone 2", "source_data": { "address": "NO_MATCH", "full_name": "NO_MATCH" }, "validation": { "address": "no_match", "full_name": "no_match" } } ] } ``` ## Returned data The exact fields surfaced in `source_data` depend on what the registry returns. The generated example for `gbr_kingdom_phone_2` currently documents this normalized shape: * `address` * `date_of_birth` * `first_name` * `last_name` ## Pricing & SLAs United Kingdom Phone 2 queries are billed only when Didit receives a conclusive result from the validation source. * **Per-call price:** \$0.96 USD. * **Billing:** per successful query. You are not charged when the registry is unreachable, when required fields are missing, or when the request is rejected before reaching the source. * **Latency:** typical p95 \< 2 s. * **Availability:** 99.9% per quarter on Didit's side; downstream source availability varies by country and dataset. ## Continue reading * [United Kingdom Database Validation overview](/api-reference/database-validation/united-kingdom) * [Database Validation overview](/core-technology/database-validation/overview) * [Outcome Codes](/core-technology/database-validation/database-validation-outcome-codes) # United Kingdom Residential Source: https://docs.didit.me/api-reference/database-validation/united-kingdom/residential POST /v3/database-validation/ Aggregated service of government and public records, background records, and public professional profiles. Authoritative real-time identity lookup for United Kingdom. Real-time lookup, pay-per-call.
Aggregated service of government and public records, background records, and public professional profiles. Didit exposes this service through `POST /v3/database-validation/` so you can verify the submitted data against the authoritative source and receive normalized match results. ## Coverage * **Coverage:** \~ 90% * **Country:** United Kingdom * **Service ID:** `gbr_kingdom_residential` * **Data domain:** Address * **Category:** Residential ## Inputs | Field | Required | Example | | --------------------- | -------: | ------------------- | | `first_name` | Yes | `John` | | `last_name` | Yes | `Doe` | | `address.street_1` | Yes | `123 Sample Street` | | `address.postal_code` | Yes | `10001` | | `date_of_birth` | No | `1990-01-01` | | `phone` | No | `+15550101000` | | `address.street_2` | No | `Unit 4` | | `address.city` | No | `Sample City` | | `address.region` | No | `Sample State` | | `vendor_data` | No | `user-1234` | * **Required inputs:** `first_name`, `last_name`, `address.street_1`, `address.postal_code` * **Optional inputs:** `date_of_birth`, `phone`, `address.street_2`, `address.city`, `address.region`, `vendor_data` * **Consent:** Not required * **Workflow availability:** Available in workflow * **Coverage:** \~ 90% * **Price:** \$0.25 per successful query ## Body parameters ISO 3166-1 alpha-3 country code for this database service. Example: `GBR` Array containing this service ID. Pinning the service keeps the request scoped to this exact database. Example: `gbr_kingdom_residential` Given name to validate. Example: `John` Family name to validate. Example: `Doe` Structured residential address object. Use `street_1`, `street_2`, `city`, `region`, `postal_code`, and `country`. A complete legacy address string is still accepted but not recommended. Example: `{"street_1":"123 Sample Street","street_2":"Unit 4","city":"Sample City","region":"Sample State","postal_code":"10001","country":"US"}` Date of birth in `YYYY-MM-DD` format. Example: `1990-01-01` Phone number in international format. Example: `+15550101000` Your stable user reference for this person, such as your internal user ID. Didit uses it to link standalone checks to the same end user and reduce duplicate-detection noise. Example: `user-1234` ## Input rules & validation notes * For address services, send structured address fields instead of a single `address` string when possible. * `address.street_1` is the street address, including street number and street type. * `address.street_2` is apartment, unit, building, floor, or extra address line. Send it only when you have it. * `address.city` is city, suburb, district, locality, or neighborhood. * `address.region` is state, province, region, or town. * `address.postal_code` is postcode or postal code. * Address-based database services require at least street address and postal code; requests rejected before source lookup are not charged. ## How to call it ```bash cURL theme={null} curl -X POST "https://verification.didit.me/v3/database-validation/" \ -H "x-api-key: YOUR_API_KEY" \ -F "issuing_state=GBR" \ -F "services=gbr_kingdom_residential" \ -F "vendor_data=user-1234" \ -F "first_name=John" \ -F "last_name=Doe" \ -F 'address={"street_1":"123 Sample Street","street_2":"Unit 4","city":"Sample City","region":"Sample State","postal_code":"10001","country":"US"}' ``` Every successful call returns HTTP `200`. The **`outcome_code`** field tells you what actually happened — distinguishing, for example, a real biometric mismatch (`BIOMETRIC_NO_MATCH`) from a selfie that could not be read (`BIOMETRIC_IMAGE_UNUSABLE`). The `status` shown is the default feature status; your configured [Partial Match / No Match actions](/core-technology/database-validation/database-validation-warnings) can override it. **`MATCH`** — The registry confirmed the identity and every checked field matched. ```json 200 OK — MATCH theme={null} { "request_id": "req_01H…", "status": "Approved", "issuing_state": "GBR", "match_type": "full_match", "validations": [ { "outcome_code": "MATCH", "service_id": "gbr_kingdom_residential", "service_name": "United Kingdom Residential", "source_data": { "address": "123 Sample Street", "date_of_birth": "1990-01-01", "first_name": "John", "last_name": "Doe" }, "validation": { "address": "full_match", "full_name": "full_match" } } ] } ``` **`PARTIAL_MATCH`** — The identification number was found but one or more personal fields (usually name or date of birth) did not fully match. ```json 200 OK — PARTIAL_MATCH theme={null} { "request_id": "req_01H…", "status": "In Review", "issuing_state": "GBR", "match_type": "partial_match", "validations": [ { "outcome_code": "PARTIAL_MATCH", "service_id": "gbr_kingdom_residential", "service_name": "United Kingdom Residential", "source_data": { "address": "123 Sample Street", "date_of_birth": "1990-01-01", "first_name": "John", "last_name": "Doe" }, "validation": { "address": "full_match", "full_name": "no_match" } } ] } ``` **`NO_MATCH`** — The registry returned no match for the submitted data. ```json 200 OK — NO_MATCH theme={null} { "request_id": "req_01H…", "status": "Declined", "issuing_state": "GBR", "match_type": "no_match", "validations": [ { "outcome_code": "NO_MATCH", "service_id": "gbr_kingdom_residential", "service_name": "United Kingdom Residential", "source_data": { "address": "NO_MATCH", "full_name": "NO_MATCH" }, "validation": { "address": "no_match", "full_name": "no_match" } } ] } ``` ## Returned data The exact fields surfaced in `source_data` depend on what the registry returns. The generated example for `gbr_kingdom_residential` currently documents this normalized shape: * `address` * `date_of_birth` * `first_name` * `last_name` ## Pricing & SLAs United Kingdom Residential queries are billed only when Didit receives a conclusive result from the validation source. * **Per-call price:** \$0.25 USD. * **Billing:** per successful query. You are not charged when the registry is unreachable, when required fields are missing, or when the request is rejected before reaching the source. * **Latency:** typical p95 \< 2 s. * **Availability:** 99.9% per quarter on Didit's side; downstream source availability varies by country and dataset. ## Continue reading * [United Kingdom Database Validation overview](/api-reference/database-validation/united-kingdom) * [Database Validation overview](/core-technology/database-validation/overview) * [Outcome Codes](/core-technology/database-validation/database-validation-outcome-codes) # United States of America - United States Credit Bureau Source: https://docs.didit.me/api-reference/database-validation/united-states/credit-bureau POST /v3/database-validation/ Aggregated service of credit header data and other services. Authoritative real-time identity lookup for United States. Real-time lookup, pay-per-call.
Aggregated service of credit header data and other services. Didit exposes this service through `POST /v3/database-validation/` so you can verify the submitted data against the authoritative source and receive normalized match results. ## Coverage * **Coverage:** \~ 90% * **Country:** United States * **Service ID:** `usa_states_credit_bureau` * **Data domain:** Financial * **Category:** CreditBureau ## Inputs | Field | Required | Example | | --------------------- | -------: | ---------------------- | | `first_name` | Yes | `John` | | `last_name` | Yes | `Doe` | | `date_of_birth` | No | `1990-01-01` | | `address.street_1` | No | `123 Sample Street` | | `address.street_2` | No | `Unit 4` | | `address.city` | No | `Sample City` | | `address.region` | No | `Sample State` | | `address.postal_code` | No | `10001` | | `phone` | No | `+15550101000` | | `ssn` | No | `123456789` | | `email` | No | `john.doe@example.com` | | `vendor_data` | No | `user-1234` | * **Required inputs:** `first_name`, `last_name` * **Optional inputs:** `date_of_birth`, `address.street_1`, `address.street_2`, `address.city`, `address.region`, `address.postal_code`, `phone`, `ssn`, `email`, `vendor_data` * **Consent:** Not required * **Workflow availability:** Available in workflow * **Coverage:** \~ 90% * **Price:** \$0.15 per successful query ## Body parameters ISO 3166-1 alpha-3 country code for this database service. Example: `USA` Array containing this service ID. Pinning the service keeps the request scoped to this exact database. Example: `usa_states_credit_bureau` Given name to validate. Example: `John` Family name to validate. Example: `Doe` Date of birth in `YYYY-MM-DD` format. Example: `1990-01-01` Structured residential address object. Use `street_1`, `street_2`, `city`, `region`, `postal_code`, and `country`. A complete legacy address string is still accepted but not recommended. Example: `{"street_1":"123 Sample Street","street_2":"Unit 4","city":"Sample City","region":"Sample State","postal_code":"10001","country":"US"}` Phone number in international format. Example: `+15550101000` `ssn` value required by this database service. Example: `123456789` Email address. Example: `john.doe@example.com` Your stable user reference for this person, such as your internal user ID. Didit uses it to link standalone checks to the same end user and reduce duplicate-detection noise. Example: `user-1234` ## Input rules & validation notes * `address` is optional for this service. You can send one complete `address` string and Didit will split it into structured address elements when possible, or you can send the structured fields explicitly. * US Social Security Number or ITIN - full 9 digits (dashes optional) or only the last 4 digits * `ssn` must match `(?:\d{9}|\d{3}-\d{2}-\d{4}|\d{4})`. * For `ssn`, send either the full 9-digit SSN/ITIN (dashes optional) or only its last 4 digits. * Beyond the required `first_name` and `last_name`, include at least one more field from `date_of_birth`, `address`, `phone`, `ssn`, or `email`. A name-only request is rejected before the provider lookup (and not charged); `date_of_birth` gives the most reliable match. * For address services, send structured address fields instead of a single `address` string when possible. * `address.street_1` is the street address, including street number and street type. * `address.street_2` is apartment, unit, building, floor, or extra address line. Send it only when you have it. * `address.city` is city, suburb, district, locality, or neighborhood. * `address.region` is state, province, region, or town. * `address.postal_code` is postcode or postal code. * Address-based database services require at least street address and postal code; requests rejected before source lookup are not charged. ## How to call it ```bash cURL theme={null} curl -X POST "https://verification.didit.me/v3/database-validation/" \ -H "x-api-key: YOUR_API_KEY" \ -F "issuing_state=USA" \ -F "services=usa_states_credit_bureau" \ -F "vendor_data=user-1234" \ -F "first_name=John" \ -F "last_name=Doe" ``` Every successful call returns HTTP `200`. The **`outcome_code`** field tells you what actually happened — distinguishing, for example, a real biometric mismatch (`BIOMETRIC_NO_MATCH`) from a selfie that could not be read (`BIOMETRIC_IMAGE_UNUSABLE`). The `status` shown is the default feature status; your configured [Partial Match / No Match actions](/core-technology/database-validation/database-validation-warnings) can override it. **`MATCH`** — The registry confirmed the identity and every checked field matched. ```json 200 OK — MATCH theme={null} { "request_id": "req_01H…", "status": "Approved", "issuing_state": "USA", "match_type": "full_match", "validations": [ { "outcome_code": "MATCH", "service_id": "usa_states_credit_bureau", "service_name": "United States of America - United States Credit Bureau", "source_data": { "address": "123 Sample Street", "address_match_score": "1.000", "city": "Sample City", "date_of_birth": "1990-01-01", "first_name": "John", "full_name": "John Doe", "last_name": "Doe", "name_match_score": "1.000", "postal_code": "10001", "state": "Sample State", "street": "sample_value", "verifications": { "full_name": true } }, "validation": { "full_name": "full_match" } } ] } ``` **`NO_MATCH`** — The registry returned no match for the submitted data. ```json 200 OK — NO_MATCH theme={null} { "request_id": "req_01H…", "status": "Declined", "issuing_state": "USA", "match_type": "no_match", "validations": [ { "outcome_code": "NO_MATCH", "service_id": "usa_states_credit_bureau", "service_name": "United States of America - United States Credit Bureau", "source_data": { "full_name": "NO_MATCH" }, "validation": { "full_name": "no_match" } } ] } ``` ## Returned data The exact fields surfaced in `source_data` depend on what the registry returns. The generated example for `usa_states_credit_bureau` currently documents this normalized shape: * `address` * `address_match_score` * `city` * `date_of_birth` * `first_name` * `full_name` * `last_name` * `name_match_score` * `postal_code` * `state` * `street` ## Pricing & SLAs United States of America - United States Credit Bureau queries are billed only when Didit receives a conclusive result from the validation source. * **Per-call price:** \$0.15 USD. * **Billing:** per successful query. You are not charged when the registry is unreachable, when required fields are missing, or when the request is rejected before reaching the source. * **Latency:** typical p95 \< 2 s. * **Availability:** 99.9% per quarter on Didit's side; downstream source availability varies by country and dataset. ## Continue reading * [United States Database Validation overview](/api-reference/database-validation/united-states) * [Database Validation overview](/core-technology/database-validation/overview) * [Outcome Codes](/core-technology/database-validation/database-validation-outcome-codes) # United States of America - United States Death Check (SSDMF) Source: https://docs.didit.me/api-reference/database-validation/united-states/death-check POST /v3/database-validation/ The official Social Security Death Master File. Authoritative real-time identity lookup for United States. Real-time lookup, pay-per-call.
The official Social Security Death Master File. Didit exposes this service through `POST /v3/database-validation/` so you can verify the submitted data against the authoritative source and receive normalized match results. ## Coverage * **Coverage:** 100%\* * **Country:** United States * **Service ID:** `usa_states_death_check` * **Data domain:** Other * **Category:** DeathRecord ## Inputs | Field | Required | Example | | --------------- | -------: | ------------ | | `first_name` | Yes | `John` | | `last_name` | Yes | `Doe` | | `middle_name` | No | `Demo` | | `date_of_birth` | No | `1990-01-01` | | `ssn` | No | `123456789` | | `vendor_data` | No | `user-1234` | * **Required inputs:** `first_name`, `last_name` * **Optional inputs:** `middle_name`, `date_of_birth`, `ssn`, `vendor_data` * **Consent:** Not required * **Workflow availability:** Available in workflow * **Coverage:** 100%\* * **Price:** \$0.06 per successful query ## Body parameters ISO 3166-1 alpha-3 country code for this database service. Example: `USA` Array containing this service ID. Pinning the service keeps the request scoped to this exact database. Example: `usa_states_death_check` Given name to validate. Example: `John` Family name to validate. Example: `Doe` Middle name, when available. Example: `Demo` Date of birth in `YYYY-MM-DD` format. Example: `1990-01-01` `ssn` value required by this database service. Example: `123456789` Your stable user reference for this person, such as your internal user ID. Didit uses it to link standalone checks to the same end user and reduce duplicate-detection noise. Example: `user-1234` ## Input rules & validation notes * US Social Security Number or ITIN - full 9 digits (dashes optional) or only the last 4 digits * `ssn` must match `(?:\d{9}|\d{3}-\d{2}-\d{4}|\d{4})`. * For `ssn`, send either the full 9-digit SSN/ITIN (dashes optional) or only its last 4 digits. ## How to call it ```bash cURL theme={null} curl -X POST "https://verification.didit.me/v3/database-validation/" \ -H "x-api-key: YOUR_API_KEY" \ -F "issuing_state=USA" \ -F "services=usa_states_death_check" \ -F "vendor_data=user-1234" \ -F "first_name=John" \ -F "last_name=Doe" ``` Every successful call returns HTTP `200`. The **`outcome_code`** field tells you what actually happened — distinguishing, for example, a real biometric mismatch (`BIOMETRIC_NO_MATCH`) from a selfie that could not be read (`BIOMETRIC_IMAGE_UNUSABLE`). The `status` shown is the default feature status; your configured [Partial Match / No Match actions](/core-technology/database-validation/database-validation-warnings) can override it. **`MATCH`** — The registry confirmed the identity and every checked field matched. ```json 200 OK — MATCH theme={null} { "request_id": "req_01H…", "status": "Approved", "issuing_state": "USA", "match_type": "full_match", "validations": [ { "outcome_code": "MATCH", "service_id": "usa_states_death_check", "service_name": "United States of America - United States Death Check (SSDMF)", "source_data": { "date_of_birth": "1990-01-01", "first_name": "John", "full_name": "John Doe", "last_name": "Doe", "name_match_score": "1.000", "verifications": { "full_name": true } }, "validation": { "full_name": "full_match" } } ] } ``` **`NO_MATCH`** — The registry returned no match for the submitted data. ```json 200 OK — NO_MATCH theme={null} { "request_id": "req_01H…", "status": "Declined", "issuing_state": "USA", "match_type": "no_match", "validations": [ { "outcome_code": "NO_MATCH", "service_id": "usa_states_death_check", "service_name": "United States of America - United States Death Check (SSDMF)", "source_data": { "full_name": "NO_MATCH" }, "validation": { "full_name": "no_match" } } ] } ``` ## Returned data The exact fields surfaced in `source_data` depend on what the registry returns. The generated example for `usa_states_death_check` currently documents this normalized shape: * `date_of_birth` * `first_name` * `full_name` * `last_name` * `name_match_score` ## Pricing & SLAs United States of America - United States Death Check (SSDMF) queries are billed only when Didit receives a conclusive result from the validation source. * **Per-call price:** \$0.06 USD. * **Billing:** per successful query. You are not charged when the registry is unreachable, when required fields are missing, or when the request is rejected before reaching the source. * **Latency:** typical p95 \< 2 s. * **Availability:** 99.9% per quarter on Didit's side; downstream source availability varies by country and dataset. ## Continue reading * [United States Database Validation overview](/api-reference/database-validation/united-states) * [Database Validation overview](/core-technology/database-validation/overview) * [Outcome Codes](/core-technology/database-validation/database-validation-outcome-codes) # United States of America - United States Financial Services Source: https://docs.didit.me/api-reference/database-validation/united-states/financial-services POST /v3/database-validation/ Aggregated service of government and public records, background records, and other services. Authoritative real-time identity lookup for United States. Real-time lookup, pay-per-call.
Aggregated service of government and public records, background records, and other services. Didit exposes this service through `POST /v3/database-validation/` so you can verify the submitted data against the authoritative source and receive normalized match results. ## Coverage * **Coverage:** \~ 85% * **Country:** United States * **Service ID:** `usa_states_financial_services` * **Data domain:** Financial * **Category:** FinancialServices ## Inputs | Field | Required | Example | | --------------------- | -------: | ---------------------- | | `first_name` | Yes | `John` | | `last_name` | Yes | `Doe` | | `date_of_birth` | Yes | `1990-01-01` | | `address.street_1` | No | `123 Sample Street` | | `address.street_2` | No | `Unit 4` | | `address.city` | No | `Sample City` | | `address.region` | No | `Sample State` | | `address.postal_code` | No | `10001` | | `phone` | No | `+15550101000` | | `ssn` | No | `123456789` | | `email` | No | `john.doe@example.com` | | `vendor_data` | No | `user-1234` | * **Required inputs:** `first_name`, `last_name`, `date_of_birth` * **Optional inputs:** `address.street_1`, `address.street_2`, `address.city`, `address.region`, `address.postal_code`, `phone`, `ssn`, `email`, `vendor_data` * **Consent:** Not required * **Workflow availability:** Available in workflow * **Coverage:** \~ 85% * **Price:** \$0.12 per successful query ## Body parameters ISO 3166-1 alpha-3 country code for this database service. Example: `USA` Array containing this service ID. Pinning the service keeps the request scoped to this exact database. Example: `usa_states_financial_services` Given name to validate. Example: `John` Family name to validate. Example: `Doe` Date of birth in `YYYY-MM-DD` format. Example: `1990-01-01` Structured residential address object. Use `street_1`, `street_2`, `city`, `region`, `postal_code`, and `country`. A complete legacy address string is still accepted but not recommended. Example: `{"street_1":"123 Sample Street","street_2":"Unit 4","city":"Sample City","region":"Sample State","postal_code":"10001","country":"US"}` Phone number in international format. Example: `+15550101000` `ssn` value required by this database service. Example: `123456789` Email address. Example: `john.doe@example.com` Your stable user reference for this person, such as your internal user ID. Didit uses it to link standalone checks to the same end user and reduce duplicate-detection noise. Example: `user-1234` ## Input rules & validation notes * `address` is optional for this service. You can send one complete `address` string and Didit will split it into structured address elements when possible, or you can send the structured fields explicitly. * US Social Security Number or ITIN - full 9 digits (dashes optional) or only the last 4 digits * `ssn` must match `(?:\d{9}|\d{3}-\d{2}-\d{4}|\d{4})`. * For `ssn`, send either the full 9-digit SSN/ITIN (dashes optional) or only its last 4 digits. * This service requires `first_name`, `last_name`, and `date_of_birth`, which already meets the source's minimum of a name plus one more identity field. Optional fields (`ssn`, `address`, `phone`, `email`) further strengthen the match. * For address services, send structured address fields instead of a single `address` string when possible. * `address.street_1` is the street address, including street number and street type. * `address.street_2` is apartment, unit, building, floor, or extra address line. Send it only when you have it. * `address.city` is city, suburb, district, locality, or neighborhood. * `address.region` is state, province, region, or town. * `address.postal_code` is postcode or postal code. * Address-based database services require at least street address and postal code; requests rejected before source lookup are not charged. ## How to call it ```bash cURL theme={null} curl -X POST "https://verification.didit.me/v3/database-validation/" \ -H "x-api-key: YOUR_API_KEY" \ -F "issuing_state=USA" \ -F "services=usa_states_financial_services" \ -F "vendor_data=user-1234" \ -F "first_name=John" \ -F "last_name=Doe" \ -F "date_of_birth=1990-01-01" ``` Every successful call returns HTTP `200`. The **`outcome_code`** field tells you what actually happened — distinguishing, for example, a real biometric mismatch (`BIOMETRIC_NO_MATCH`) from a selfie that could not be read (`BIOMETRIC_IMAGE_UNUSABLE`). The `status` shown is the default feature status; your configured [Partial Match / No Match actions](/core-technology/database-validation/database-validation-warnings) can override it. **`MATCH`** — The registry confirmed the identity and every checked field matched. ```json 200 OK — MATCH theme={null} { "request_id": "req_01H…", "status": "Approved", "issuing_state": "USA", "match_type": "full_match", "validations": [ { "outcome_code": "MATCH", "service_id": "usa_states_financial_services", "service_name": "United States of America - United States Financial Services", "source_data": { "address": "123 Sample Street", "address_match_score": "1.000", "city": "Sample City", "date_of_birth": "1990-01-01", "first_name": "John", "full_name": "John Doe", "last_name": "Doe", "name_match_score": "1.000", "postal_code": "10001", "state": "Sample State", "street": "sample_value", "verifications": { "date_of_birth": true, "full_name": true } }, "validation": { "date_of_birth": "full_match", "full_name": "full_match" } } ] } ``` **`PARTIAL_MATCH`** — The identification number was found but one or more personal fields (usually name or date of birth) did not fully match. ```json 200 OK — PARTIAL_MATCH theme={null} { "request_id": "req_01H…", "status": "In Review", "issuing_state": "USA", "match_type": "partial_match", "validations": [ { "outcome_code": "PARTIAL_MATCH", "service_id": "usa_states_financial_services", "service_name": "United States of America - United States Financial Services", "source_data": { "address": "123 Sample Street", "address_match_score": "1.000", "city": "Sample City", "date_of_birth": "1990-01-01", "first_name": "John", "full_name": "John Doe", "last_name": "Doe", "name_match_score": "1.000", "postal_code": "10001", "state": "Sample State", "street": "sample_value", "verifications": { "date_of_birth": true, "full_name": false } }, "validation": { "date_of_birth": "full_match", "full_name": "no_match" } } ] } ``` **`NO_MATCH`** — The registry returned no match for the submitted data. ```json 200 OK — NO_MATCH theme={null} { "request_id": "req_01H…", "status": "Declined", "issuing_state": "USA", "match_type": "no_match", "validations": [ { "outcome_code": "NO_MATCH", "service_id": "usa_states_financial_services", "service_name": "United States of America - United States Financial Services", "source_data": { "date_of_birth": "NO_MATCH", "full_name": "NO_MATCH" }, "validation": { "date_of_birth": "no_match", "full_name": "no_match" } } ] } ``` ## Returned data The exact fields surfaced in `source_data` depend on what the registry returns. The generated example for `usa_states_financial_services` currently documents this normalized shape: * `address` * `address_match_score` * `city` * `date_of_birth` * `first_name` * `full_name` * `last_name` * `name_match_score` * `postal_code` * `state` * `street` ## Pricing & SLAs United States of America - United States Financial Services queries are billed only when Didit receives a conclusive result from the validation source. * **Per-call price:** \$0.12 USD. * **Billing:** per successful query. You are not charged when the registry is unreachable, when required fields are missing, or when the request is rejected before reaching the source. * **Latency:** typical p95 \< 2 s. * **Availability:** 99.9% per quarter on Didit's side; downstream source availability varies by country and dataset. ## Continue reading * [United States Database Validation overview](/api-reference/database-validation/united-states) * [Database Validation overview](/core-technology/database-validation/overview) * [Outcome Codes](/core-technology/database-validation/database-validation-outcome-codes) # United States of America - United States Phone 2 Source: https://docs.didit.me/api-reference/database-validation/united-states/phone-2 POST /v3/database-validation/ Verifies input data to mobile network operators phone data. Authoritative real-time identity lookup for United States. Real-time lookup, pay-per-call.
Verifies input data to mobile network operators phone data. Didit exposes this service through `POST /v3/database-validation/` so you can verify the submitted data against the authoritative source and receive normalized match results. ## Coverage * **Coverage:** > 90% * **Country:** United States * **Service ID:** `usa_states_phone_2` * **Data domain:** Telecom * **Category:** Telecom ## Inputs | Field | Required | Example | | --------------------- | -------: | ------------------- | | `first_name` | Yes | `John` | | `last_name` | Yes | `Doe` | | `address.street_1` | Yes | `123 Sample Street` | | `address.postal_code` | Yes | `10001` | | `phone` | Yes | `+15550101000` | | `date_of_birth` | No | `1990-01-01` | | `ssn` | No | `123456789` | | `address.street_2` | No | `Unit 4` | | `address.city` | No | `Sample City` | | `address.region` | No | `Sample State` | | `vendor_data` | No | `user-1234` | * **Required inputs:** `first_name`, `last_name`, `address.street_1`, `address.postal_code`, `phone` * **Optional inputs:** `date_of_birth`, `ssn`, `address.street_2`, `address.city`, `address.region`, `vendor_data` * **Consent:** Not required * **Workflow availability:** Available in workflow * **Coverage:** > 90% * **Price:** \$0.15 per successful query ## Body parameters ISO 3166-1 alpha-3 country code for this database service. Example: `USA` Array containing this service ID. Pinning the service keeps the request scoped to this exact database. Example: `usa_states_phone_2` Given name to validate. Example: `John` Family name to validate. Example: `Doe` Structured residential address object. Use `street_1`, `street_2`, `city`, `region`, `postal_code`, and `country`. A complete legacy address string is still accepted but not recommended. Example: `{"street_1":"123 Sample Street","street_2":"Unit 4","city":"Sample City","region":"Sample State","postal_code":"10001","country":"US"}` Phone number in international format. Example: `+15550101000` Date of birth in `YYYY-MM-DD` format. Example: `1990-01-01` `ssn` value required by this database service. Example: `123456789` Your stable user reference for this person, such as your internal user ID. Didit uses it to link standalone checks to the same end user and reduce duplicate-detection noise. Example: `user-1234` ## Input rules & validation notes * US Social Security Number (9 digits, with optional dashes) * `ssn` must match `(?:\d{9}|\d{3}-\d{2}-\d{4})`. * For `ssn`, send the full 9-digit SSN/ITIN (dashes optional). Unlike the US Credit Bureau and Financial Services checks, this service does not accept the last-4-digits form. * For address services, send structured address fields instead of a single `address` string when possible. * `address.street_1` is the street address, including street number and street type. * `address.street_2` is apartment, unit, building, floor, or extra address line. Send it only when you have it. * `address.city` is city, suburb, district, locality, or neighborhood. * `address.region` is state, province, region, or town. * `address.postal_code` is postcode or postal code. * Address-based database services require at least street address and postal code; requests rejected before source lookup are not charged. ## How to call it ```bash cURL theme={null} curl -X POST "https://verification.didit.me/v3/database-validation/" \ -H "x-api-key: YOUR_API_KEY" \ -F "issuing_state=USA" \ -F "services=usa_states_phone_2" \ -F "vendor_data=user-1234" \ -F "first_name=John" \ -F "last_name=Doe" \ -F 'address={"street_1":"123 Sample Street","street_2":"Unit 4","city":"Sample City","region":"Sample State","postal_code":"10001","country":"US"}' \ -F "phone=+15550101000" ``` Every successful call returns HTTP `200`. The **`outcome_code`** field tells you what actually happened — distinguishing, for example, a real biometric mismatch (`BIOMETRIC_NO_MATCH`) from a selfie that could not be read (`BIOMETRIC_IMAGE_UNUSABLE`). The `status` shown is the default feature status; your configured [Partial Match / No Match actions](/core-technology/database-validation/database-validation-warnings) can override it. **`MATCH`** — The registry confirmed the identity and every checked field matched. ```json 200 OK — MATCH theme={null} { "request_id": "req_01H…", "status": "Approved", "issuing_state": "USA", "match_type": "full_match", "validations": [ { "outcome_code": "MATCH", "service_id": "usa_states_phone_2", "service_name": "United States of America - United States Phone 2", "source_data": { "address": "123 Sample Street", "date_of_birth": "1990-01-01", "first_name": "John", "last_name": "Doe" }, "validation": { "address": "full_match", "full_name": "full_match" } } ] } ``` **`PARTIAL_MATCH`** — The identification number was found but one or more personal fields (usually name or date of birth) did not fully match. ```json 200 OK — PARTIAL_MATCH theme={null} { "request_id": "req_01H…", "status": "In Review", "issuing_state": "USA", "match_type": "partial_match", "validations": [ { "outcome_code": "PARTIAL_MATCH", "service_id": "usa_states_phone_2", "service_name": "United States of America - United States Phone 2", "source_data": { "address": "123 Sample Street", "date_of_birth": "1990-01-01", "first_name": "John", "last_name": "Doe" }, "validation": { "address": "full_match", "full_name": "no_match" } } ] } ``` **`NO_MATCH`** — The registry returned no match for the submitted data. ```json 200 OK — NO_MATCH theme={null} { "request_id": "req_01H…", "status": "Declined", "issuing_state": "USA", "match_type": "no_match", "validations": [ { "outcome_code": "NO_MATCH", "service_id": "usa_states_phone_2", "service_name": "United States of America - United States Phone 2", "source_data": { "address": "NO_MATCH", "full_name": "NO_MATCH" }, "validation": { "address": "no_match", "full_name": "no_match" } } ] } ``` ## Returned data The exact fields surfaced in `source_data` depend on what the registry returns. The generated example for `usa_states_phone_2` currently documents this normalized shape: * `address` * `date_of_birth` * `first_name` * `last_name` ## Pricing & SLAs United States of America - United States Phone 2 queries are billed only when Didit receives a conclusive result from the validation source. * **Per-call price:** \$0.15 USD. * **Billing:** per successful query. You are not charged when the registry is unreachable, when required fields are missing, or when the request is rejected before reaching the source. * **Latency:** typical p95 \< 2 s. * **Availability:** 99.9% per quarter on Didit's side; downstream source availability varies by country and dataset. ## Continue reading * [United States Database Validation overview](/api-reference/database-validation/united-states) * [Database Validation overview](/core-technology/database-validation/overview) * [Outcome Codes](/core-technology/database-validation/database-validation-outcome-codes) # United States of America - United States Residential Source: https://docs.didit.me/api-reference/database-validation/united-states/residential POST /v3/database-validation/ Aggregated service of government and public records, background records, and public professional profiles. Authoritative real-time identity lookup for United States. Real-time lookup, pay-per-call.
Aggregated service of government and public records, background records, and public professional profiles. Didit exposes this service through `POST /v3/database-validation/` so you can verify the submitted data against the authoritative source and receive normalized match results. ## Coverage * **Coverage:** \~ 90% * **Country:** United States * **Service ID:** `usa_states_residential` * **Data domain:** Address * **Category:** Residential ## Inputs | Field | Required | Example | | --------------------- | -------: | ---------------------- | | `first_name` | Yes | `John` | | `last_name` | Yes | `Doe` | | `date_of_birth` | Yes | `1990-01-01` | | `address.street_1` | Yes | `123 Sample Street` | | `address.postal_code` | Yes | `10001` | | `phone` | No | `+15550101000` | | `ssn` | No | `123456789` | | `email` | No | `john.doe@example.com` | | `address.street_2` | No | `Unit 4` | | `address.city` | No | `Sample City` | | `address.region` | No | `Sample State` | | `vendor_data` | No | `user-1234` | * **Required inputs:** `first_name`, `last_name`, `date_of_birth`, `address.street_1`, `address.postal_code` * **Optional inputs:** `phone`, `ssn`, `email`, `address.street_2`, `address.city`, `address.region`, `vendor_data` * **Consent:** Not required * **Workflow availability:** Available in workflow * **Coverage:** \~ 90% * **Price:** \$0.60 per successful query ## Body parameters ISO 3166-1 alpha-3 country code for this database service. Example: `USA` Array containing this service ID. Pinning the service keeps the request scoped to this exact database. Example: `usa_states_residential` Given name to validate. Example: `John` Family name to validate. Example: `Doe` Date of birth in `YYYY-MM-DD` format. Example: `1990-01-01` Structured residential address object. Use `street_1`, `street_2`, `city`, `region`, `postal_code`, and `country`. A complete legacy address string is still accepted but not recommended. Example: `{"street_1":"123 Sample Street","street_2":"Unit 4","city":"Sample City","region":"Sample State","postal_code":"10001","country":"US"}` Phone number in international format. Example: `+15550101000` `ssn` value required by this database service. Example: `123456789` Email address. Example: `john.doe@example.com` Your stable user reference for this person, such as your internal user ID. Didit uses it to link standalone checks to the same end user and reduce duplicate-detection noise. Example: `user-1234` ## Input rules & validation notes * must be at least 2 characters long * US Social Security Number (9 digits, with optional dashes) * `ssn` must match `(?:\d{9}|\d{3}-\d{2}-\d{4})`. * For `ssn`, send the full 9-digit SSN/ITIN (dashes optional). Unlike the US Credit Bureau and Financial Services checks, this service does not accept the last-4-digits form. * For address services, send structured address fields instead of a single `address` string when possible. * `address.street_1` is the street address, including street number and street type. * `address.street_2` is apartment, unit, building, floor, or extra address line. Send it only when you have it. * `address.city` is city, suburb, district, locality, or neighborhood. * `address.region` is state, province, region, or town. * `address.postal_code` is postcode or postal code. * Address-based database services require at least street address and postal code; requests rejected before source lookup are not charged. ## How to call it ```bash cURL theme={null} curl -X POST "https://verification.didit.me/v3/database-validation/" \ -H "x-api-key: YOUR_API_KEY" \ -F "issuing_state=USA" \ -F "services=usa_states_residential" \ -F "vendor_data=user-1234" \ -F "first_name=John" \ -F "last_name=Doe" \ -F "date_of_birth=1990-01-01" \ -F 'address={"street_1":"123 Sample Street","street_2":"Unit 4","city":"Sample City","region":"Sample State","postal_code":"10001","country":"US"}' ``` Every successful call returns HTTP `200`. The **`outcome_code`** field tells you what actually happened — distinguishing, for example, a real biometric mismatch (`BIOMETRIC_NO_MATCH`) from a selfie that could not be read (`BIOMETRIC_IMAGE_UNUSABLE`). The `status` shown is the default feature status; your configured [Partial Match / No Match actions](/core-technology/database-validation/database-validation-warnings) can override it. **`MATCH`** — The registry confirmed the identity and every checked field matched. ```json 200 OK — MATCH theme={null} { "request_id": "req_01H…", "status": "Approved", "issuing_state": "USA", "match_type": "full_match", "validations": [ { "outcome_code": "MATCH", "service_id": "usa_states_residential", "service_name": "United States of America - United States Residential", "source_data": { "address": "123 Sample Street", "address_match_score": "1.000", "city": "Sample City", "date_of_birth": "1990-01-01", "first_name": "John", "full_name": "John Doe", "last_name": "Doe", "name_match_score": "1.000", "postal_code": "10001", "state": "Sample State", "street": "sample_value", "verifications": { "address": true, "date_of_birth": true, "full_name": true } }, "validation": { "address": "full_match", "date_of_birth": "full_match", "full_name": "full_match" } } ] } ``` **`PARTIAL_MATCH`** — The identification number was found but one or more personal fields (usually name or date of birth) did not fully match. ```json 200 OK — PARTIAL_MATCH theme={null} { "request_id": "req_01H…", "status": "In Review", "issuing_state": "USA", "match_type": "partial_match", "validations": [ { "outcome_code": "PARTIAL_MATCH", "service_id": "usa_states_residential", "service_name": "United States of America - United States Residential", "source_data": { "address": "123 Sample Street", "address_match_score": "1.000", "city": "Sample City", "date_of_birth": "1990-01-01", "first_name": "John", "full_name": "John Doe", "last_name": "Doe", "name_match_score": "1.000", "postal_code": "10001", "state": "Sample State", "street": "sample_value", "verifications": { "address": true, "date_of_birth": true, "full_name": false } }, "validation": { "address": "full_match", "date_of_birth": "full_match", "full_name": "no_match" } } ] } ``` **`NO_MATCH`** — The registry returned no match for the submitted data. ```json 200 OK — NO_MATCH theme={null} { "request_id": "req_01H…", "status": "Declined", "issuing_state": "USA", "match_type": "no_match", "validations": [ { "outcome_code": "NO_MATCH", "service_id": "usa_states_residential", "service_name": "United States of America - United States Residential", "source_data": { "address": "NO_MATCH", "date_of_birth": "NO_MATCH", "full_name": "NO_MATCH" }, "validation": { "address": "no_match", "date_of_birth": "no_match", "full_name": "no_match" } } ] } ``` ## Returned data The exact fields surfaced in `source_data` depend on what the registry returns. The generated example for `usa_states_residential` currently documents this normalized shape: * `address` * `address_match_score` * `city` * `date_of_birth` * `first_name` * `full_name` * `last_name` * `name_match_score` * `postal_code` * `state` * `street` ## Pricing & SLAs United States of America - United States Residential queries are billed only when Didit receives a conclusive result from the validation source. * **Per-call price:** \$0.60 USD. * **Billing:** per successful query. You are not charged when the registry is unreachable, when required fields are missing, or when the request is rejected before reaching the source. * **Latency:** typical p95 \< 2 s. * **Availability:** 99.9% per quarter on Didit's side; downstream source availability varies by country and dataset. ## Continue reading * [United States Database Validation overview](/api-reference/database-validation/united-states) * [Database Validation overview](/core-technology/database-validation/overview) * [Outcome Codes](/core-technology/database-validation/database-validation-outcome-codes) # Uruguay - CI verification Source: https://docs.didit.me/api-reference/database-validation/uruguay/cedula POST /v3/database-validation/ Verifies Uruguayan Cédula data against Dirección Nacional del Registro de Estado Civil government records. Authoritative real-time identity lookup for Uruguay. Real-time lookup, pay-per-call.
Verifies Uruguayan Cédula data against Dirección Nacional del Registro de Estado Civil government records. Didit exposes this service through `POST /v3/database-validation/` so you can verify the submitted data against the authoritative source and receive normalized match results. ## Coverage * **Coverage:** 90-95% * **Country:** Uruguay * **Service ID:** `ury_cedula` * **Data domain:** Identity * **Category:** NationalIDRegistry ## Inputs | Field | Required | Example | | ----------------- | -------: | ------------ | | `personal_number` | Yes | `1111111` | | `date_of_birth` | Yes | `1990-01-01` | | `first_name` | No | `John` | | `last_name` | No | `Doe` | | `vendor_data` | No | `user-1234` | * **Required inputs:** `personal_number`, `date_of_birth` * **Optional inputs:** `first_name`, `last_name`, `vendor_data` * **Consent:** Not required * **Workflow availability:** Available in workflow * **Coverage:** 90-95% * **Price:** \$0.20 per successful query ## Body parameters ISO 3166-1 alpha-3 country code for this database service. Example: `URY` Array containing this service ID. Pinning the service keeps the request scoped to this exact database. Example: `ury_cedula` Country-specific personal identity number. Example: `1111111` Date of birth in `YYYY-MM-DD` format. Example: `1990-01-01` Given name to validate. Example: `John` Family name to validate. Example: `Doe` Your stable user reference for this person, such as your internal user ID. Didit uses it to link standalone checks to the same end user and reduce duplicate-detection noise. Example: `user-1234` ## Input rules & validation notes * Uruguayan CI (7-9 digits) * `personal_number` must contain digits only; remove spaces, hyphens, and punctuation before sending the request. * `personal_number` must be 7-9 characters long. ## How to call it ```bash cURL theme={null} curl -X POST "https://verification.didit.me/v3/database-validation/" \ -H "x-api-key: YOUR_API_KEY" \ -F "issuing_state=URY" \ -F "services=ury_cedula" \ -F "vendor_data=user-1234" \ -F "personal_number=1111111" \ -F "date_of_birth=1990-01-01" ``` Every successful call returns HTTP `200`. The **`outcome_code`** field tells you what actually happened — distinguishing, for example, a real biometric mismatch (`BIOMETRIC_NO_MATCH`) from a selfie that could not be read (`BIOMETRIC_IMAGE_UNUSABLE`). The `status` shown is the default feature status; your configured [Partial Match / No Match actions](/core-technology/database-validation/database-validation-warnings) can override it. **`MATCH`** — The registry confirmed the identity and every checked field matched. ```json 200 OK — MATCH theme={null} { "request_id": "req_01H…", "status": "Approved", "issuing_state": "URY", "match_type": "full_match", "validations": [ { "outcome_code": "MATCH", "service_id": "ury_cedula", "service_name": "Uruguay - CI verification", "source_data": { "date_of_birth": "1990-01-01", "first_name": "John", "full_name": "John Doe", "identification_number": "SAMPLE-ID-12345", "last_name": "Doe" }, "validation": { "date_of_birth": "full_match", "identification_number": "full_match" } } ] } ``` **`PARTIAL_MATCH`** — The identification number was found but one or more personal fields (usually name or date of birth) did not fully match. ```json 200 OK — PARTIAL_MATCH theme={null} { "request_id": "req_01H…", "status": "In Review", "issuing_state": "URY", "match_type": "partial_match", "validations": [ { "outcome_code": "PARTIAL_MATCH", "service_id": "ury_cedula", "service_name": "Uruguay - CI verification", "source_data": { "date_of_birth": "1990-01-01", "first_name": "John", "full_name": "John Doe", "identification_number": "SAMPLE-ID-12345", "last_name": "Doe" }, "validation": { "date_of_birth": "no_match", "identification_number": "full_match" } } ] } ``` **`NO_MATCH`** — The registry returned no match for the submitted data. ```json 200 OK — NO_MATCH theme={null} { "request_id": "req_01H…", "status": "Declined", "issuing_state": "URY", "match_type": "no_match", "validations": [ { "outcome_code": "NO_MATCH", "service_id": "ury_cedula", "service_name": "Uruguay - CI verification", "source_data": { "date_of_birth": "NO_MATCH", "identification_number": "NO_MATCH" }, "validation": { "date_of_birth": "no_match", "identification_number": "no_match" } } ] } ``` ## Returned data The exact fields surfaced in `source_data` depend on what the registry returns. The generated example for `ury_cedula` currently documents this normalized shape: * `date_of_birth` * `first_name` * `full_name` * `identification_number` * `last_name` ## Pricing & SLAs Uruguay - CI verification queries are billed only when Didit receives a conclusive result from the validation source. * **Per-call price:** \$0.20 USD. * **Billing:** per successful query. You are not charged when the registry is unreachable, when required fields are missing, or when the request is rejected before reaching the source. * **Latency:** typical p95 \< 2 s. * **Availability:** 99.9% per quarter on Didit's side; downstream source availability varies by country and dataset. ## Continue reading * [Uruguay Database Validation overview](/api-reference/database-validation/uruguay) * [Database Validation overview](/core-technology/database-validation/overview) * [Outcome Codes](/core-technology/database-validation/database-validation-outcome-codes) # Venezuela - Cédula verification Source: https://docs.didit.me/api-reference/database-validation/venezuela/cedula POST /v3/database-validation/ Verifies Venezuelan Cédula data against CNE electoral registry records. Authoritative real-time identity lookup for Venezuela. Real-time lookup, pay-per-call.
Verifies Venezuelan Cédula data against CNE electoral registry records. Didit exposes this service through `POST /v3/database-validation/` so you can verify the submitted data against the authoritative source and receive normalized match results. ## Coverage * **Coverage:** 90-95% * **Country:** Venezuela * **Service ID:** `ven_cedula` * **Data domain:** Identity * **Category:** NationalIDRegistry ## Inputs | Field | Required | Example | | ----------------- | -------: | ------------------ | | `document_number` | Yes | `SAMPLE-DOC-12345` | | `first_name` | No | `John` | | `last_name` | No | `Doe` | | `vendor_data` | No | `user-1234` | * **Required inputs:** `document_number` * **Optional inputs:** `first_name`, `last_name`, `vendor_data` * **Consent:** Not required * **Workflow availability:** Available in workflow * **Coverage:** 90-95% * **Price:** \$0.20 per successful query ## Body parameters ISO 3166-1 alpha-3 country code for this database service. Example: `VEN` Array containing this service ID. Pinning the service keeps the request scoped to this exact database. Example: `ven_cedula` Document number extracted from or provided by the user. Example: `SAMPLE-DOC-12345` Given name to validate. Example: `John` Family name to validate. Example: `Doe` Your stable user reference for this person, such as your internal user ID. Didit uses it to link standalone checks to the same end user and reduce duplicate-detection noise. Example: `user-1234` ## Input rules & validation notes * Venezuelan Cédula (7-10 digits, optional V/E prefix) * `document_number` must be 7-12 characters long. * `document_number` must match `[VvEe]?-?\d{7,10}`. ## How to call it ```bash cURL theme={null} curl -X POST "https://verification.didit.me/v3/database-validation/" \ -H "x-api-key: YOUR_API_KEY" \ -F "issuing_state=VEN" \ -F "services=ven_cedula" \ -F "vendor_data=user-1234" \ -F "document_number=SAMPLE-DOC-12345" ``` Every successful call returns HTTP `200`. The **`outcome_code`** field tells you what actually happened — distinguishing, for example, a real biometric mismatch (`BIOMETRIC_NO_MATCH`) from a selfie that could not be read (`BIOMETRIC_IMAGE_UNUSABLE`). The `status` shown is the default feature status; your configured [Partial Match / No Match actions](/core-technology/database-validation/database-validation-warnings) can override it. **`MATCH`** — The registry confirmed the identity and every checked field matched. ```json 200 OK — MATCH theme={null} { "request_id": "req_01H…", "status": "Approved", "issuing_state": "VEN", "match_type": "full_match", "validations": [ { "outcome_code": "MATCH", "service_id": "ven_cedula", "service_name": "Venezuela - Cédula verification", "source_data": { "document_type": "sample_value", "first_name": "John", "full_name": "John Doe", "identification_number": "SAMPLE-ID-12345", "last_name": "Doe" }, "validation": { "identification_number": "full_match" } } ] } ``` **`NO_MATCH`** — The registry returned no match for the submitted data. ```json 200 OK — NO_MATCH theme={null} { "request_id": "req_01H…", "status": "Declined", "issuing_state": "VEN", "match_type": "no_match", "validations": [ { "outcome_code": "NO_MATCH", "service_id": "ven_cedula", "service_name": "Venezuela - Cédula verification", "source_data": { "identification_number": "NO_MATCH" }, "validation": { "identification_number": "no_match" } } ] } ``` ## Returned data The exact fields surfaced in `source_data` depend on what the registry returns. The generated example for `ven_cedula` currently documents this normalized shape: * `document_type` * `first_name` * `full_name` * `identification_number` * `last_name` ## Pricing & SLAs Venezuela - Cédula verification queries are billed only when Didit receives a conclusive result from the validation source. * **Per-call price:** \$0.20 USD. * **Billing:** per successful query. You are not charged when the registry is unreachable, when required fields are missing, or when the request is rejected before reaching the source. * **Latency:** typical p95 \< 2 s. * **Availability:** 99.9% per quarter on Didit's side; downstream source availability varies by country and dataset. ## Continue reading * [Venezuela Database Validation overview](/api-reference/database-validation/venezuela) * [Database Validation overview](/core-technology/database-validation/overview) * [Outcome Codes](/core-technology/database-validation/database-validation-outcome-codes) # Healthcheck Source: https://docs.didit.me/api-reference/healthcheck openapi-healthcheck.json GET /system/healthcheck Public unauthenticated liveness probe. Returns `HTTP 200` with `{status: "ok", timestamp}` when service, DB, cache, and broker are healthy. # API Reference Source: https://docs.didit.me/api-reference/overview Complete REST API reference for Didit identity verification. Sessions, standalone endpoints, management API, and OpenAPI spec. Pay-per-use pricing. Didit offers **two complementary approaches** to identity verification. Understanding the difference is essential for choosing the right integration for your use case. *** ## Hosted Sessions (Recommended for User-Facing Flows) Hosted sessions are the **recommended approach** for most integrations. When you create a session, Didit generates a `verification_url` that you present to your user. The user completes the entire verification flow in Didit's optimized interface, and you receive the results via webhook or API. ### How It Works Your server calls `POST /v3/session/` with a workflow ID. Didit returns a `verification_url` and `session_token`. Redirect the user, embed via iframe, or initialize a native SDK using the session token. The user follows the guided flow in Didit's optimized UI — ID capture, liveness, and any additional steps. Didit sends a webhook to your server with the verification decision, or you poll via the retrieve API. ### Why Sessions Are Recommended | Advantage | Details | | --------------------------- | ----------------------------------------------------------------------------------------------- | | **Optimized UX** | The verification interface is continuously A/B tested globally for the highest completion rates | | **Camera handling** | Smart camera selection, auto-capture, quality checks, and device compatibility built in | | **Guided flow** | Step-by-step instructions, real-time feedback, and error recovery for the user | | **Multi-feature workflows** | Chain multiple features (ID + Liveness + AML + Phone + Email) in a single flow | | **Security** | Anti-spoofing, active liveness detection, and device fingerprinting embedded in the flow | | **Compliance** | Session-level audit trails, consent capture, and data retention policies handled automatically | | **Localization** | 49 languages with automatic browser detection | | **Mobile-native** | Native SDKs for iOS, Android, React Native, and Flutter | | **No maintenance** | Didit handles all UI updates, browser/device bugs, and camera edge cases | ### When to Use Sessions * **User onboarding / KYC** — New users sign up and need to verify their identity * **Age verification** — Confirm users meet minimum age requirements * **Re-verification** — Periodically re-verify existing users * **Biometric authentication** — Users authenticate with their face for sensitive actions * **Multi-step compliance** — Flows requiring ID + Liveness + AML + Phone in one go * **Any scenario where the end user is present** and interacts directly ### Session Endpoints | Endpoint | Purpose | | --------------------------------------------------- | ------------------------------------------------------ | | [Create Session](/sessions-api/create-session) | Generate a verification URL for a user | | [Retrieve Session](/sessions-api/retrieve-session) | Get the full results and decision for a session | | [List Sessions](/sessions-api/list-sessions) | Query and filter all sessions | | [Delete Session](/sessions-api/delete-session) | Remove a session and all associated data | | [Generate PDF](/sessions-api/generate-pdf) | Export a verification report as PDF | | [Share Session](/sessions-api/share-session/share) | Generate a share token for Reusable KYC with a partner | | [Import Shared](/sessions-api/share-session/import) | Import a session shared by a partner (Reusable KYC) | *** ## Standalone APIs (For Server-to-Server Processing) Standalone APIs let you call individual verification features **directly from your server** without any end-user UI. You send the data (images, documents, names) and receive structured results. ### How It Works Your server calls a standalone endpoint (e.g., `POST /v3/id-verification/`) with the required data — images, documents, or JSON fields. Didit processes the request synchronously and returns structured verification results in the response. ### When to Use Standalone APIs | Use Case | Example | | ------------------------------------- | --------------------------------------------------------------------------------- | | **Backend processing** | You already have document images from your own capture UI and need to verify them | | **Batch verification** | Processing bulk identity documents uploaded by an operations team | | **Custom UX** | You've built your own capture flow and want to use Didit only for the analysis | | **Server-to-server checks** | AML screening a list of customers, without any user interaction | | **Automated pipelines** | CI/CD or cron-based compliance re-checks (e.g., daily AML monitoring) | | **Integration with existing systems** | Connecting Didit's verification to your existing document management system | | **Single-feature calls** | You only need one feature (e.g., just AML screening or just face matching) | ### Available Standalone APIs **Identity & Documents** | API | What It Does | | -------------------------------------------------------------------- | -------------------------------------------------------------------------- | | [ID Verification](/standalone-apis/id-verification) | Extract and validate data from ID documents (front + back images) | | [Proof of Address](/standalone-apis/proof-of-address) | Verify address documents (utility bills, bank statements, government docs) | | [Database Validation](/core-technology/database-validation/overview) | Cross-check user data against government databases | **Document AI** | API | What It Does | | ------------------------------------------- | ------------------------------------------------------------------------------------------------------- | | [Document AI](/standalone-apis/document-ai) | Extract the fields you define from any document (PDF or image), with name matching and tampering checks | **Biometrics & Face** | API | What It Does | | ----------------------------------------------------- | ------------------------------------------------------------------- | | [Passive Liveness](/standalone-apis/passive-liveness) | Verify a real person is present (anti-spoofing) from a single image | | [Face Match](/standalone-apis/face-match) | Compare two faces to determine if they are the same person | | [Face Search](/standalone-apis/face-search) | Search for a face across all previously verified sessions (1:N) | | [Age Estimation](/standalone-apis/age-estimation) | Estimate a person's age from a facial image | **Compliance & Risk** | API | What It Does | | ----------------------------------------------- | ------------------------------------------------------------------ | | [AML Screening](/standalone-apis/aml-screening) | Screen persons or companies against sanctions, PEP, and watchlists | **Business Verification (KYB)** | API | What It Does | | ----------------------------------------------------------- | -------------------------------------------------------------------------------------------------------- | | [KYB Registry Search](/standalone-apis/kyb-registry-search) | Search company registries by name, registration number, and country; up to \$0.50 per successful request | | [KYB Registry Select](/standalone-apis/kyb-registry-select) | Retrieve the full registry profile (officers, beneficial owners, addresses) for a selected company | *** ## Side-by-Side Comparison | | Hosted Sessions | Standalone APIs | | ----------------------- | ------------------------------------- | ----------------------------------------------- | | **Integration effort** | Low — redirect, iframe, or SDK | Medium — you handle data capture and submission | | **User interaction** | Yes — user completes flow in Didit UI | No — server-to-server only | | **Camera/capture** | Handled by Didit (optimized) | You provide the images/data | | **Multi-feature flows** | Yes — chain features in a workflow | One feature per API call | | **UX optimization** | Continuously A/B tested | You control the UX | | **Localization** | 49 languages, auto-detected | N/A (no UI) | | **Webhooks** | Automatic status notifications | N/A (synchronous response) | | **Response time** | Async (user completes at their pace) | Synchronous (seconds) | | **Best for** | User-facing onboarding & verification | Backend processing & automation | | **Console visibility** | Full session lifecycle in dashboard | Appears in Manual Checks section | *** ## Can I Use Both? **Yes.** Many teams combine both approaches: 1. **Sessions for onboarding** — New users go through the full hosted verification flow during sign-up 2. **Standalone AML for ongoing monitoring** — A cron job re-screens all approved users nightly against updated watchlists 3. **Standalone Face Search for duplicate detection** — When a new session is approved, your server calls Face Search to check for duplicates 4. **Standalone ID Verification for operations** — Your compliance team uploads documents manually for edge-case reviews ### Example: Combined Architecture | Your Application | Didit API | Type | | ---------------------------- | ------------------------------ | ---------------- | | **User sign-up flow** | Sessions API (hosted UI) | User-facing | | **Nightly AML re-screening** | Standalone AML API | Server-to-server | | **Ops team document review** | Standalone ID Verification API | Server-to-server | | **Duplicate face detection** | Standalone Face Search API | Server-to-server | *** ## Getting Started *** # Create Application Source: https://docs.didit.me/auth-api/create-application POST /organizations/me/{org_id}/applications/ Create an application inside an organization. The response includes `api_key`; persist it now (recoverable via GET). Requires owner/admin JWT. Use this endpoint when you need to separate verification traffic, credentials, branding, or reporting inside the same organization. This is especially useful for **resellers** that create one application per customer. It also works well when your own company has multiple products, brands, regions, staging/production environments, or use cases that should not share the same API key and application-level settings. All Auth API endpoints use `https://apx.didit.me/auth/v2`. Use the returned `api_key` as `x-api-key` when calling `https://verification.didit.me/v3/...` endpoints such as sessions and workflows. # Get Application Credentials Source: https://docs.didit.me/auth-api/get-credentials GET /organizations/me/{org_id}/applications/{app_id}/ Read one application's full record including `client_id` and `api_key`. Use this to recover a lost `api_key`. # Programmatic Login Source: https://docs.didit.me/auth-api/login POST /programmatic/login/ Authenticate any verified email/password Didit account and receive an RS256 JWT pair (default lifetime 86400s). Console-created email/password accounts can use this endpoint; OAuth-only console accounts must set a password first. # Register Account Source: https://docs.didit.me/auth-api/register POST /programmatic/register/ Step 1 of programmatic onboarding. Creates a pending account and emails a 6-char code (10 min TTL). Rate limit: 5/IP/hour. # Update Application Source: https://docs.didit.me/auth-api/update-application PATCH /organizations/me/{org_id}/applications/{app_id}/ Update application metadata (name, URLs, redirect URIs). `api_key` and `client_id` are never rotated. Requires owner/admin JWT. Use this endpoint to keep each application aligned with the customer, brand, environment, or internal use case it represents. For resellers, this lets you rename or update each customer application without sharing credentials across customers. For direct customers, it helps separate products, regions, or environments while keeping everything under one organization. This endpoint updates application metadata. The `api_key` stays the same unless you rotate credentials separately. # Verify Email & Get Credentials Source: https://docs.didit.me/auth-api/verify-email POST /programmatic/verify-email/ Step 2 of onboarding. Exchanges the 6-char code for a verified account, a default org+app, and a JWT pair. Persist the returned `api_key`. # Business AML Screening Source: https://docs.didit.me/business-verification/aml Screen companies, UBOs, and officers against global sanctions, PEP, and watchlist databases. Entity AML included; $0.20 per person. No contracts. Business verification includes AML screening at two levels: the **company entity** and all **identified individuals** (beneficial owners and officers). This ensures comprehensive compliance coverage. The same two-score system used in user verification applies — see [AML screening overview](/core-technology/aml-screening/overview), [risk score](/core-technology/aml-screening/aml-risk-score), and [match score](/core-technology/aml-screening/aml-match-score) for the underlying model. ## Company-level AML The company itself is screened against global watchlists as a legal entity: | Check | Description | | -------------------------- | --------------------------------------------------------------------------------- | | **Sanctions** | International and national sanctions lists (OFAC, EU, UN, etc.) | | **Regulatory enforcement** | Regulatory warnings, fines, and enforcement actions | | **Adverse media** | News articles about financial crime, fraud, or legal issues involving the company | Company AML uses the same [two-score risk system](/core-technology/aml-screening/overview) as user verification: * **Match score** — how confident the system is that the match refers to the same entity * **Risk score** — how risky the matched entity is based on the category, country, and severity Company-level screening produces: | Field | Description | | ------------------------- | ---------------------------------------------- | | `company_aml_score` | Overall AML risk score for the company (0–100) | | `company_aml_total_hits` | Total number of watchlist matches found | | `company_aml_screened_at` | Timestamp of the most recent screening | ## Person-level AML Every identified beneficial owner and officer is individually screened against: | Check | Description | | --------------------- | -------------------------------------------------------------------------------------- | | **Sanctions** | Individual sanctions across all major lists | | **PEP** | Politically Exposed Persons at all levels (heads of state through to close associates) | | **Criminal records** | Global and local criminal databases | | **Adverse media** | News articles mentioning the individual in connection with financial crime | | **Fitness & probity** | Financial regulator fitness and probity registers | ## Screening flow Company name, registration number, country, and all identified persons are extracted from the registry lookup. The company entity is screened against corporate sanctions, regulatory enforcement, and adverse media databases. Each beneficial owner and officer is screened individually against PEP, sanctions, criminal, and adverse media databases. Each match receives a match score and risk score. Matches below the match score threshold are classified as false positives. Remaining matches determine the AML status. The business session's overall AML status reflects the highest-risk result across the company and all screened individuals. ## Configuration AML screening for business verification uses the same configurable thresholds as user verification: | Setting | Description | | ------------------------- | --------------------------------------------------------------------------------------------- | | **Match score threshold** | Below this threshold, matches are auto-classified as false positives | | **Approve threshold** | Risk scores below this value result in an Approved AML status | | **Review threshold** | Risk scores above this value result in a Declined AML status; between thresholds is In Review | These thresholds can be set per workflow in the Business Console. ## Ongoing monitoring If ongoing AML monitoring is enabled, all screened entities (company and individuals) are re-screened daily against updated watchlists. Any new matches trigger a webhook notification so your compliance team can take action. ### Enabling ongoing monitoring Toggle ongoing monitoring per business session from the [Business Console](/business-verification/console) or via the API: | Setting | Description | | ------------------------------- | ------------------------------------------------------ | | `is_ongoing_monitoring_enabled` | Enable or disable daily re-screening for this business | | `last_aml_bill_date` | Timestamp of the most recent billed screening cycle | When enabled, Didit re-screens the company entity and all identified individuals against updated watchlists. New or changed matches generate a `data.updated` webhook event with `session_kind: "business"` (or `business.data.updated` when the entity profile changes). Ongoing monitoring incurs a per-screening fee for each monitoring cycle. Review your billing settings to understand the cost impact before enabling monitoring across all business sessions. ## Next steps Two-score system, watchlists, thresholds. Sanctions, watchlists, and insolvency sources used at the company level. Ongoing rescans and webhook events. # AML Coverage Source: https://docs.didit.me/business-verification/aml-coverage Global sanctions, regulatory watchlists, and insolvency registers powering Didit's KYB AML screening across 220+ countries. Pay-per-call, no contracts. Didit's business AML screening leverages a curated set of global publishers tailored to **legal entities**: international sanctions regimes, national regulatory watchlists, and insolvency / bankruptcy registers. Company-level matches surface alongside person-level matches for beneficial owners and officers — see the [AML screening page](/business-verification/aml) for how the two layers combine. ### 1. **Sanctions Screening** We maintain up‑to‑date coverage of all major **multilateral sanctions, debarment, and exclusion lists** published by international organizations and development banks, including: * **United Nations Security Council** consolidated list * **European Union** consolidated financial sanctions and travel-ban lists * **Multilateral development banks** (World Bank, ADB, AIIB, IDB, AfDB, EBRD, EIB, CDB) debarment / ineligibility registers * **Specialized international watchlists** (IOSCO investor alerts, EU Air Safety List, Uyghur Human Rights Project) ### 2. **Regulatory & Enforcement Watchlists** We screen against **government and regulatory watchlists** published by national authorities responsible for financial markets, trade, transport, energy, and consumer protection. Coverage spans agencies in the United States, Canada, Colombia, and Brazil — including securities regulators, central banks, antitrust authorities, customs and trade bodies, and procurement registries. ### 3. **Insolvency & Bankruptcy Registers** We flag companies listed in **official insolvency, bankruptcy, and liquidation registers** across multiple jurisdictions, including India (IBBI), China's National Enterprise Bankruptcy Information Disclosure Platform, U.S. federal and state insurance guaranty associations, the FDIC, German insolvency announcements, the Polish court-business monitor, and similar registers in Australia, Chile, Indonesia, Brazil, and Belgium. *** ### Granular Taxonomy & Structured Metadata Every match is enriched with structured metadata to aid remediation and risk prioritization: * **Categorization**: primary categories (Sanctions, Watchlists, Insolvency) and publisher-level subcategories * **Identifiers**: company name, registration number, jurisdiction * **Other fields**: aliases, addresses, listing date, source URL This ensures easy filtering and supports detailed differential risk workflows. *** ## Summary Table | **Risk Category** | **Key Coverage** | | ------------------------- | ------------------------------------------------------------------------------------------------- | | **Sanctions** | UN, EU, OFAC, World Bank, ADB, AIIB, IDB, AfDB, EBRD, EIB, IOSCO, EU Air Safety List | | **Regulatory Watchlists** | Securities regulators, central banks, trade authorities, antitrust bodies, procurement registries | | **Insolvency Registers** | National bankruptcy boards, deposit insurance corporations, court insolvency monitors | *** ### Sanctions Below is a table of the international sanctions lists included in our business AML screening process: | Publisher | Country | Category | | ------------------------------------------------------------------------------- | ---------------- | --------- | | Anti-Corruption Foundation (ACF International) — Sanctions Tracker | 🌐 International | Sanctions | | Solomon Islands Government-Ministry of Commerce, Industry, Labour & Immigration | 🌐 International | Sanctions | | European Investment Bank - Exclusions | 🌐 International | Sanctions | | Caribbean Development Bank - Sanctions | 🌐 International | Sanctions | | European National Bank - Supervisory Sanctions | 🌐 International | Sanctions | | Uyghur Human Rights Project - Sanctions | 🌐 International | Sanctions | | EU Sanctions - Consolidated List of Travel Bans | 🌐 International | Sanctions | | EU Consolidated Sanctions | 🌐 International | Sanctions | | Inter-American Development Bank (IDB) - Sanctioned Firms | 🌐 International | Sanctions | | Asian Infrastructure Investment Bank - Debarment List | 🌐 International | Sanctions | | United Nations Security Council - Consolidated List | 🌐 International | Sanctions | | European Commission - The EU Air Safety List | 🌐 International | Sanctions | | Asian Development bank - Sanction List | 🌐 International | Sanctions | | European Bank for Reconstruction and Development - Ineligible Entities | 🌐 International | Sanctions | | African Development Bank - Debarred Entities | 🌐 International | Sanctions | | European Union - Consolidated List of EU Financial Sanctions | 🌐 International | Sanctions | | International Organization of Securities Commission - Investor Alerts Portal | 🌐 International | Sanctions | | The World Bank - Debarred Firms and Individuals | 🌐 International | Sanctions |

18 sources across 1 jurisdiction

### Regulatory Watchlists Below is a table of the regulatory and enforcement watchlists included in our business AML screening process: | Publisher | Country | Category | | ------------------------------------------------------------------ | ------------------ | ---------- | | Office of Foreign Assets Control | 🇺🇸 United States | Watchlists | | Federal Trade Commission | 🇺🇸 United States | Watchlists | | International Trade Administration, U.S. Department of Commerce | 🇺🇸 United States | Watchlists | | U.S Securities and Exchange Commission | 🇺🇸 United States | Watchlists | | Federal Reserve Bank | 🇺🇸 United States | Watchlists | | Food and Drug Administration | 🇺🇸 United States | Watchlists | | Federal Energy Regulatory Commission | 🇺🇸 United States | Watchlists | | Transport Canada | 🇨🇦 Canada | Watchlists | | Ontario Securities Commission | 🇨🇦 Canada | Watchlists | | BC Securities Commission | 🇨🇦 Canada | Watchlists | | Government of Canada | 🇨🇦 Canada | Watchlists | | Canadian Transportation Agency | 🇨🇦 Canada | Watchlists | | Canada Energy Regulator | 🇨🇦 Canada | Watchlists | | Superintendency of Industry and Commerce | 🇨🇴 Colombia | Watchlists | | National Directorate of Taxes and Customs | 🇨🇴 Colombia | Watchlists | | Office of the Attorney General; Republic of Colombia | 🇨🇴 Colombia | Watchlists | | Superintendency of the Solidarity Economy | 🇨🇴 Colombia | Watchlists | | Superintendence of Ports and Transport | 🇨🇴 Colombia | Watchlists | | Judicial Branch; Superior Council of the Judiciary | 🇨🇴 Colombia | Watchlists | | Comptroller General of Santander | 🇨🇴 Colombia | Watchlists | | Secop Electronic Public Procurement System | 🇨🇴 Colombia | Watchlists | | Ministry of Justice and Public Security | 🇧🇷 Brazil | Watchlists | | National Electric Energy Agency | 🇧🇷 Brazil | Watchlists | | National Civil Aviation Agency | 🇧🇷 Brazil | Watchlists | | Administrative Council for Economic Defense | 🇧🇷 Brazil | Watchlists | | Brazilian Institute of Environment and Renewable Natural Resources | 🇧🇷 Brazil | Watchlists | | Securities and Exchange Commission of Brazil | 🇧🇷 Brazil | Watchlists | | Federal Government of Brazil | 🇧🇷 Brazil | Watchlists | | Public Ministry of the State of Minas Gerais | 🇧🇷 Brazil | Watchlists | | Labor Public Ministry | 🇧🇷 Brazil | Watchlists |

30 sources across 4 countries

### Insolvency Registers Below is a table of the insolvency, bankruptcy, and liquidation registers included in our business AML screening process: | Publisher | Country | Category | | ------------------------------------------------------------------------ | ------------------ | ---------- | | Insolvency and Bankruptcy Board of India (IBBI) | 🇮🇳 India | Insolvency | | China National Enterprise Bankruptcy Information Disclosure Platform | 🇨🇳 China | Insolvency | | U.S Securities and Exchange Commission | 🇺🇸 United States | Insolvency | | Bankrupt Companies in the United States | 🇺🇸 United States | Insolvency | | National Organization of Life and Health Insurance Guaranty Associations | 🇺🇸 United States | Insolvency | | Arkansas Life and Health Insurance Guaranty Association | 🇺🇸 United States | Insolvency | | Florida Office of Insurance Regulation | 🇺🇸 United States | Insolvency | | Florida Insurance Guaranty Association | 🇺🇸 United States | Insolvency | | Des Moines Register | 🇺🇸 United States | Insolvency | | New York Liquidation Bureau (NYLB) | 🇺🇸 United States | Insolvency | | North Carolina Insurance Guaranty Association | 🇺🇸 United States | Insolvency | | Federal Deposit Insurance Corporation (FDIC) | 🇺🇸 United States | Insolvency | | Indonesia Deposit Insurance Corporation - Bank Liquidation | 🇮🇩 Indonesia | Insolvency | | Central Bank - Liquidated Companies | 🇧🇷 Brazil | Insolvency | | German Insolvency Register - insolvenzbekanntmachungen | 🇩🇪 Germany | Insolvency | | BORSE-Frankfurt | 🇩🇪 Germany | Insolvency | | Insolvenz Radar | 🇩🇪 Germany | Insolvency | | Internetowy Monitor Sądowy Gospodarczy | 🇵🇱 Poland | Insolvency | | Australian Financial Security Authority - Bankruptcy Register | 🇦🇺 Australia | Insolvency | | Chile The Superintendency of Insolvency and Re-entrepreneurship | 🇨🇱 Chile | Insolvency | | American Bankruptcy Institute Global Insolvency | 🇧🇪 Belgium | Insolvency |

21 sources across 9 countries

*** ## Next steps How company and person-level AML are combined. Full person-level watchlist coverage reference. Ongoing rescans and webhook events. # Business Profiles Source: https://docs.didit.me/business-verification/business-profiles Track verified companies across sessions with auto-created profiles, status management, tags, bulk ops, and CSV import/export. From $2.00 per check, priced per country and tier. Didit automatically creates a business profile for each company you verify, aggregating verification data and session history into a single entity. Business profiles provide a unified view of each company across all their verification sessions. Business profiles are the KYB-specific surface of the more general **Business entity** model. For the full entity model — operations, key-people linking to Users, blocklist mechanics, import/export — see [Businesses overview](/entities/businesses/overview). ## What is a business profile A business profile is created automatically when a [business session](/business-verification/overview) is submitted with a `vendor_data` identifier. If a profile with that identifier already exists, the new session is linked to it. | Field | Description | | ----------------------- | -------------------------------------------------------------- | | **Vendor data** | Your unique identifier for this business (e.g., `company-123`) | | **Display name** | Display name shown in the console | | **Legal name** | Official legal name from registry or manual entry | | **Registration number** | Company registration or incorporation number | | **Country** | Country of incorporation (ISO 3166-1 alpha-2) | ## Profile statuses | Status | Description | | --------- | -------------------------------------------------------------- | | `ACTIVE` | Business is in good standing — no issues detected | | `FLAGGED` | Business requires attention — review results or pending checks | | `BLOCKED` | Business has been blocked from further activity | Statuses can be changed manually from the console, in bulk, or automatically based on verification results. ## Session metrics Each profile tracks verification metrics across all linked sessions: | Metric | Description | | ------------------ | ---------------------------------------------------------------------- | | **Total sessions** | Number of verification sessions for this business | | **Approved** | Sessions that passed all checks | | **Declined** | Sessions that failed one or more critical checks | | **In review** | Sessions awaiting analyst review | | **Last session** | Timestamp of the most recent verification | | **First session** | Timestamp of the earliest verification | | **Last activity** | Timestamp of any recent activity (status change, session update, etc.) | ## Tags Apply tags to business profiles for categorisation and filtering. Tags are application-defined — create custom tags that fit your workflow (e.g., `high-risk`, `vip-client`, `re-verification-needed`). ## Bulk operations Manage multiple business profiles at once: | Operation | Description | | ---------------------- | ----------------------------------------------------------------------------------- | | **Bulk status update** | Change the status of selected profiles (or all profiles matching current filters) | | **CSV export** | Export profile data to CSV with configurable column selection | | **CSV import** | Import business profiles from a CSV file to pre-create profiles before verification | | **Bulk delete** | Remove selected profiles and their associated data | ### CSV import To import business profiles in bulk: 1. Download the **import template** from the console to see the expected column format 2. Populate the template with your business data 3. Upload the file — Didit creates an import job and processes rows asynchronously After completion, review the import summary for created, updated, and failed row counts. Failed rows include specific error details. ## Reviews and comments Add internal review notes to any business profile. Comments are visible to all team members with access and form part of the audit trail: * Add notes with free-text content * Mention team members by email to notify them * View the full comment history with author and timestamp ## Next steps How business verification sessions work end to end. Managing business profiles and sessions in the Business Console. Business management API endpoints. # Company Data Source: https://docs.didit.me/business-verification/company-data Automated registry lookups, company status validation, and data extraction across 220+ countries. From $2.00 per check, priced per country and tier, no contracts. When a business verification session starts, Didit queries official company registries to retrieve and validate company information. This automated lookup provides the foundation for the entire business verification process. ## Registry lookup Didit connects to company registries in supported countries to retrieve official data. In the hosted flow the user selects the country of incorporation and fills in the company name, the registration number, or both — at least one is required. Registration numbers are normalized where registries require it (for example, UK company numbers are zero-padded to eight digits), and when both identifiers are provided the registry lookup combines them. ### Pre-filling the search with `expected_details` If you already know the company, pass `expected_details` (`company_name`, `registry_country`, `registration_number`) when [creating the session](/sessions-api/create-session). The hosted flow pre-selects and locks the country (and the state for state-level registries like `US-CA`), pre-fills the matching search fields, and runs the asserted search automatically — the user lands directly on their company's result. Both fields stay editable so the user can correct a wrong assertion. Prefill only: selecting a different company than asserted does not produce a warning. ### Search types Registry searches support two modes: | Mode | Description | | ------------ | --------------------------------------------------------------------------------------------------- | | **Exact** | Matches the company name or registration number precisely | | **Contains** | Matches companies whose name contains the search term — useful when the exact legal name is unknown | ### Search workflow The registry lookup follows an asynchronous workflow: Didit queries the registry with the selected country and the identifiers provided — company name, registration number, or both combined. The response's `searched_by` field reports how results were matched (`name`, `registration_number`, or `registration_number_and_name`), and the hosted UI offers a one-tap "Search as company name instead" override on registration-number results. The search runs asynchronously. Poll the search status until results are resolved. Large registries may take a few seconds to return results. Review the returned companies and select the correct match. Didit links the selected company to the KYB check and populates all available data. If the company is not found in the registry, submit company data manually. The session continues with the provided data, and `is_from_registry` is set to `false`. ### Retrieved data | Field | Description | | --------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------ | | `company_name` | Legal name as registered with the authority | | `registration_number` | Official company registration or incorporation number | | `country_code` | Country of incorporation (ISO 3166-1 alpha-3) | | `company_type` | Legal entity type (Ltd, LLC, PLC, SA, GmbH, SL, etc.) | | `registry_status` | Current company status from the registry (`active`, `dissolved`, `struck_off`, etc.) | | `incorporation_date` | Date the company was originally registered | | `registered_address` | Official registered office address | | `tax_number` | Tax identification number where available | | `alternative_names` | Trade names, dbas, former legal names, or original-language names as a text value | | `legal_entity_identifier` | LEI — for financial institutions and listed entities | | `nature_of_business` | Short description of the business (in the registry's language) | | `registered_capital` | Authorized / issued capital as an `{amount, currency}` object | | `location_of_registration` | City / subdivision of the registry of record | | `control_scheme` | Control / governance scheme where the registry exposes it | | `website`, `email`, `phone` | Contact details on file with the registry | | `addresses[]` | Additional registered or trading addresses | | `industries[]` | Industry classification codes (SIC, NACE, or local equivalents) | | `accounts` | Filing dates when reported, including `last_annual_return_date` and `last_agm_date`. Annual returns and meetings are distinct from financial accounts. | | `financial_summary` | Summary financial data where the registry publishes it (revenue, employees, filing status) | | `confirmed_by_user_at` | Timestamp when the end user confirmed or edited the registry data | | `last_console_edit_at` | Timestamp of the last console-side edit by an analyst | | `is_editable` | `true` while registry-sourced data can still be edited by the end user in the hosted flow | | `is_from_registry` | `true` for registry-sourced companies, `false` for manual entry | | `fetch_status` | `pending`, `resolved`, or `failed` — registry lookup state | | `verification_status` | `verified`, `failed`, or `unknown` | ### Company statuses | Status | Description | | ------------------ | ---------------------------------------------------- | | **Active** | Company is currently active and in good standing | | **Dissolved** | Company has been formally dissolved | | **Struck off** | Removed from the register (e.g., for non-compliance) | | **In liquidation** | Company is in the process of being wound up | | **Dormant** | Registered but not currently trading | Companies with a status other than **Active** may be automatically flagged or declined depending on your workflow configuration. ### Data source indicator Each company record includes an `is_from_registry` flag: * **`true`** — data was retrieved from an official company registry * **`false`** — data was manually submitted because the company was not found in the registry The `fetch_status` field tracks whether the registry lookup has completed, failed, or is still in progress. ## Data tiers and pricing The registry check is billed once per selected company, at the price of the tier delivered for that company's country. Hosted workflow searches have no separate search fee. Standalone API searches can incur a \$0.50 fee per successful request; see [search billing](/standalone-apis/kyb-registry-search). See [KYB registry pricing](/getting-started/kyb-registry-pricing) for the full per-country table. | Tier | What you get | | ---------------- | ----------------------------------------------------------------------------------------------------- | | **Lite** | The fields above: company profile, identifiers, status, registered address, activity, and officers | | **Shareholders** | Lite plus the direct shareholders (natural persons and corporate entities) with their ownership bands | | **UBOs** | Shareholders plus the ultimate beneficial owners resolved through the ownership chain | A hosted workflow picks the tier per country from *Workflows → KYB Registry Check → Countries*. Where the registry holds no ownership record for a company, a Shareholders or UBO request is delivered and billed at the highest tier the country's registries can serve — usually Lite. A company that is not found and is entered manually (`is_from_registry: false`) is billed a flat **\$0.75** — the search still ran, even though no registry record was returned. Lite returns the company profile only — no shareholders, UBOs, or ownership structure: ```json theme={null} { "company_name": "ACME HOLDINGS PTY LTD", "registration_number": "094447122", "country_code": "AU", "registry_status": "active", "incorporation_date": "2000-09-12", "company_type": "Proprietary Limited", "registered_address": "Sydney, NSW, 2000", "tax_number": null, "vat_number": null, "website": null, "is_from_registry": true } ``` The Shareholders tier adds `ownership_structure` and shareholder entries plus directors/officers. The UBOs tier additionally resolves beneficial owners with ownership percentages. See [Ownership](/business-verification/ownership) and [Officers & directors](/business-verification/officers). ## Registry data vs user-provided data Didit keeps registry-returned data and user-confirmed data as **separate audit records**, with a merged canonical view used by downstream checks. Every company carries three related blocks: | Field | Description | | -------------------------------------------------------------------------------------------------------------- | ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | | `registry_data` | Raw payload returned by the registry. Immutable — kept as an audit record of exactly what the registry said, unchanged. | | `user_provided_data` | What the end user confirmed or edited during the registry-confirmation step in the hosted flow. | | Top-level canonical fields (`company_name`, `registration_number`, `country_code`, `incorporation_date`, etc.) | The merged truth — user-confirmed data when present, registry data as fallback. Downstream features (document OCR cross-check, AML screening, risk assessment) run against the canonical view. | The `confirmed_by_user_at` timestamp marks when the end user confirmed or edited the registry data. While that timestamp is still null and `is_editable` is `true`, the end user can continue to modify fields inside the hosted flow. For **manual-entry companies** (`is_from_registry: false`), `user_provided_data` is the only source and `is_editable` becomes `false` after the user submits. Analysts can see the two sources side-by-side in the [Business Console](/business-verification/console) session review and diff what the registry said vs what the user confirmed. ## Configurable registry form fields You control which company-data fields the hosted verification flow asks for during the registry-confirmation step. Configure them in the Business Console: open the workflow editor, select the **KYB Registry check** node, and switch to the **Fields** tab. Each field has one of three states: | State | Behavior | | ------------ | ----------------------------------------------------------------- | | **Hidden** | The field is not shown in the hosted flow and is not collected. | | **Optional** | The field is shown; the user can leave it empty. | | **Required** | The field is shown and must be filled before the user can submit. | Three fields are always shown and always required — they identify the company and cannot be configured: `company_name`, `country_code`, and `region` (state/region, where the registry is regional). The 16 configurable fields: `registration_number`, `incorporation_date`, `legal_address`, `vat_number`, `alternative_names`, `tax_number`, `company_type`, `legal_entity_identifier`, `location_of_registration`, `nature_of_business`, `registered_capital_amount`, `registered_capital_currency`, `website`, `email`, `phone`, `control_scheme` By default — and for all existing workflows — only `incorporation_date` is **Required**; every other configurable field is **Optional**, so the form behaves exactly as it did before this setting existed. Requiredness is enforced server-side: submitting the registry form with a required field empty returns `400` with per-field error messages, and the hosted UI renders only the enabled fields. In the workflow API, the setting is the `kyb_registry_fields_config` object on the KYB Registry node — see [feature configs](/management-api/workflows/feature-configs#kyb-registry) for the shape. `vat_number` marked **Required** is only enforced for companies incorporated in an EU VAT country (see below) — for all other countries the field is treated as optional even when required, since there is no EU VAT number to collect. ## VAT validation (VIES) When the end user (or the registry) provides a `vat_number` for a company incorporated in the EU, Didit validates it against the European Commission's [VIES](https://ec.europa.eu/taxation_customs/vies/) service when the registry step is submitted. * **Coverage** — the 27 EU member states plus Northern Ireland (`XI`). Greek VAT numbers are checked under the `EL` prefix automatically. Companies from any other country skip validation entirely and get `vat_validation_status: "not_applicable"`. * **Prefix handling** — the number is normalized before the check, so it can be submitted with or without the country prefix (`DE123456789` and `123456789` are equivalent for a German company). The result is stored on the company and exposed in the [KYB decision payload](/business-verification/response-schema#company-block): | Field | Description | | ----------------------- | ----------------------------------------------------------------------- | | `vat_number` | The VAT number as submitted | | `vat_validation_status` | `valid`, `invalid`, `could_not_validate`, or `not_applicable` | | `vat_validated_name` | Trader name registered with VIES, when the member state discloses it | | `vat_validated_address` | Trader address registered with VIES, when the member state discloses it | | `vat_checked_at` | Timestamp of the VIES check | | Status | Meaning | | -------------------- | -------------------------------------------------------------------------- | | `valid` | VIES confirmed the VAT number is registered | | `invalid` | VIES rejected the number (not registered or malformed) | | `could_not_validate` | VIES or the member state was unavailable — the number could not be checked | | `not_applicable` | No VAT number was provided, or the company is outside the EU VAT area | **Name cross-check.** When the number is `valid` and VIES discloses the registered trader name, Didit fuzzy-compares it against the submitted company name. A meaningful divergence raises the `KYB_COMPANY_VAT_NAME_MISMATCH` warning (with `vies_name` and `submitted_name` in `additional_data`) without changing the session status — it is a soft signal for reviewers. Some member states do not disclose the name or address; the fields come back empty and no comparison runs. **Configurable actions.** Two settings on the KYB Registry check node control what an unsuccessful check does to the session (values `REVIEW`, `DECLINE`, `NO_ACTION`): | Setting | Fires when | Default | | --------------------------- | ----------------------------------------------- | -------------------------------------- | | `kyb_vat_invalid_action` | `vat_validation_status` is `invalid` | `REVIEW` — session goes to In Review | | `kyb_vat_unverified_action` | `vat_validation_status` is `could_not_validate` | `NO_ACTION` — no effect on the session | Each outcome also raises the matching warning (`KYB_COMPANY_VAT_INVALID`, `KYB_COMPANY_VAT_COULD_NOT_VALIDATE`) on the registry check — see [Business Verification warnings](/business-verification/warnings#kyb-registry-warnings). ## Data cross-referencing Didit automatically compares the user-provided / canonical data with what the registry returned, and with OCR data extracted from uploaded documents: * **Company name** — fuzzy matching to account for abbreviations and formatting differences * **Registration number** — exact match validation * **Country** — consistency check between provided and registry country * **Address** — geocoding and normalization for comparison Any inconsistencies are flagged as warnings in the session and visible to analysts in the console. ## Financial summary Where available, Didit retrieves summary financial data from the registry: * Revenue or turnover * Number of employees * SIC/NACE industry codes * Filing dates and compliance status ## Additional registry fields Depending on jurisdiction coverage, the registry response may also include: * `alternative_names` - trade names, dbas, former legal names * `legal_entity_identifier` (LEI) — for financial institutions and listed entities * `website`, `email`, `phone` — contact information on file with the registry * `nature_of_business` — short description (in the language of the registry) * `registered_capital` — authorized / issued capital as an `{amount, currency}` object All fields land in the [`business`](/business-verification/response-schema) block of the KYB decision. ## Confidence and verification status Each registry response carries a `verification_status`: | Value | Meaning | | ---------- | ---------------------------------------------------------------------------- | | `VERIFIED` | Registry returned a match and data was retrieved. | | `FAILED` | Registry returned a match but data retrieval failed (e.g. partial response). | | `UNKNOWN` | Company could not be located in any registry. | Combine with `is_from_registry` to drive your own downstream logic: | `is_from_registry` | `verification_status` | Meaning | | ------------------ | --------------------- | --------------------------------------------- | | true | VERIFIED | Fully verified against official registry | | true | FAILED | Partial — some fields may be stale or missing | | false | UNKNOWN | User-provided data only; no registry match | ## Cross-referencing outputs Each cross-reference runs per field and returns one of: * `MATCH` — provided data agrees with registry. * `MISMATCH` — meaningful divergence. Flagged as a warning. * `NO_DATA` — one side was empty; no comparison possible. Mismatches are visible per-field in the console session review. ## Risk assessment The company's overall risk level is calculated based on: | Factor | Impact | | ------------------------ | --------------------------------------------------------------- | | **Company status** | Non-active companies increase risk | | **Country risk** | Incorporation in high-risk jurisdictions increases risk | | **Age** | Recently incorporated companies may receive additional scrutiny | | **AML results** | Company-level AML screening results | | **Ownership complexity** | Multi-layered or opaque ownership structures | See [risk assessment](/business-verification/risk-assessment) for the full computation. ## Supported countries Coverage varies by country — see [supported countries](/business-verification/supported-countries) for the per-region tier breakdown. ## Next steps UBO identification and ownership chains. Where each field appears in the payload. Coverage by region. # Business Verification Console Source: https://docs.didit.me/business-verification/console Review KYB sessions in the Business Console: company data, ownership, AML results, documents, key people. From $2.00 per check, priced per country and tier, no contracts. Business verification sessions are managed in the Business Console alongside user verifications, with KYB-specific sections for registry data, documents, and key people. This page walks through the session detail view. ## Navigating to a business session From the Business Console, open *Businesses → \[business]* to see all sessions for that business, or open the session directly from the Sessions list. Business sessions show a **business** badge next to the session number so they're easy to spot in a mixed list. ## Session detail — sections A KYB session detail page shows these sections. Which sections appear depends on the features your workflow enabled. ### Overview Session summary: status, workflow used, `vendor_data`, session number, creation/expiry timestamps, per-feature status chips (KYB Registry, KYB Company AML, KYB Documents, KYB Key People, and any shared features like AML, Phone, Email, Questionnaires, Device & IP Analysis). ### KYB Registry The company block extracted from the registry (or submitted manually when not found): * **Registry data** — registry-returned fields: legal name, registration number, incorporation date, company type, registered address, tax number, industries, accounts / filing dates. * **User-provided / confirmed data** — what the end user confirmed or edited in the hosted flow, shown side-by-side with the registry data. * **Data source indicator** — `is_from_registry`, `fetch_status`, `verification_status`, `confirmed_by_user_at`. * **Financial summary** — where the registry publishes it. * **Risk level** — composite signal (`LOW`, `MEDIUM`, `HIGH`). Actions: confirm / edit canonical fields, view the raw registry payload for audit, request the end user to re-confirm. ### KYB Documents Documents grouped by document type group — Legal presence, Company details, Ownership structure, Representatives authorization. * **Per-group progress** — approved / pending / missing counts per group, and which groups are required. * **Document items** — each uploaded document with signed preview URL, OCR extract, cross-check result against the user-provided data. * **Cross-check diff** — per-field comparison between the OCR data and the canonical company data. Actions: approve or decline individual documents, request a resubmission, request an additional document, download. ### KYB Key People The key-people list — UBOs, shareholders, directors, representatives, and other officer roles — shown **side-by-side** in two buckets: * **Registry** — parties extracted from the registry check, grouped by role category. * **Submitted** — parties the business admin added during the Key People flow (source = USER). Each person shows: name, entity type (person or company), role(s) with ownership / voting percentages where relevant, KYC status of the linked child session (`Approved` / `Declined` / `Pending`), AML status, and a link to open the child KYC or KYB sub-session. The `ubo_kyc_summary` card rolls up UBO KYC progress — total / approved / flagged / pending — at the top of the section. Actions: open a child session, skip a party's verification (or require it again), request resubmission of a specific child session, view the child AML hits. **Skipping a party** exempts it from the Key People check so a KYB that cannot progress can still be settled - the usual case is a party whose individual KYC session was deleted, which leaves it with a dead link and a status that can never change. The control needs the `write:businesses` permission and, unlike the applicant-facing skip in the hosted flow, is not limited to roles with `allow_skip`. The same override is available over the API: [`PATCH /v3/session/{id}/kyb/parties/{party_uuid}/`](/sessions-api/update-data#skip-a-key-people-party). ### AML Company-level AML screening. For each hit: match score, risk score, category (sanctions, PEP, adverse media, criminal, enforcement), watchlist source, screened name. Per-hit actions: mark false positive, confirm, add note. Person-level AML hits for key people also surface here, each linked back to the relevant key person. ### Device & IP Analysis Submitter IP, country, ASN, data-center / VPN flags, device fingerprint when collected. ### Phone / Email / Questionnaires Appear only when the workflow collects them. Same feature-detail surface as on a KYC session. ### Events Chronological log of everything that happened on the session — status changes, feature completions, analyst actions, webhook deliveries. Filter by event type and date. ### Webhooks History of webhook deliveries for this session with response codes, retry counts, and raw payloads. You can resend any delivery. ### Chat Internal analyst notes with `@`-mentions. Not visible to the end user. ## Tag management Tag any business session for categorisation and later filtering. Tags appear as chips on the Overview and on the Sessions list — useful for tracking risk tiers, review stages, partner source, or any custom axis. ## Reviewer actions From any section, an analyst with the right role can: * **Approve** the session when all checks pass. * **Decline** the session if a critical issue stands. * **Request more information** — force a resubmission on specific documents or child KYC sessions. * **Override a feature status** — manually set a feature to `APPROVED` / `DECLINED` / `IN_REVIEW` with a note. * **Add a chat note** — visible to teammates, not to the user. * **Tag** the session for downstream filtering. * **View the full audit trail** of every action on the Events tab. See [Roles & permissions](/console/roles-permissions) for the matrix of who can do what. ## Business profiles Business profiles give you the durable cross-session view of each company. From *Businesses* you can search, filter, tag, bulk-update status, export CSV, and import in bulk. See [Business profiles](/business-verification/business-profiles) for details. ## Next steps The broader Business entity model across sessions. Deep reviewer walkthroughs across KYB and KYC. Configuring KYB workflows. # Documents Source: https://docs.didit.me/business-verification/documents Collect and verify corporate documents — incorporation certificates, articles, financials — with OCR and registry cross-referencing. Document collection is billed separately from registry retrieval. Business verification includes structured document collection to validate company information beyond what's available in registries. ## Pricing In the current staging release, KYB document collection costs **USD 0.20 per workflow step**, independent of how many documents are uploaded in that step. Re-uploading a document in the same step does not add another fee; a separate document-collection step has its own charge. Production rollout of this billing change is pending. Registry retrieval, company and person AML, and linked KYC are separate charges. The 500 free document-capture ID checks do not cover KYB document collection. ## Document groups Documents are organized into four structured groups, each representing a category of evidence needed for business verification: | Group | Description | Examples | | --------------------------------- | ----------------------------------------------------------- | ----------------------------------------------------------- | | **Legal presence** | Documents proving the company legally exists | Certificate of incorporation, business registration | | **Company details** | Documents describing the company's operations | Articles of association, memorandum of association | | **Ownership structure** | Documents proving the ownership chain | Shareholder register, share certificates, UBO declarations | | **Representatives authorization** | Documents proving authority to act on behalf of the company | Power of attorney, board resolutions, authorization letters | Each group tracks its own progress with per-group summaries: total documents expected, approved, pending review, and missing. The business session's overall documents status aggregates across all groups. ## Document types | Category | Examples | | ------------------------ | -------------------------------------------------------------------------------- | | **Formation documents** | Certificate of incorporation, articles of association, memorandum of association | | **Ownership documents** | Shareholder register, share certificates, UBO declarations | | **Address documents** | Utility bills, bank statements, or lease agreements for the registered address | | **Financial documents** | Annual accounts, audit reports, financial statements | | **Tax documents** | Tax registration certificates, tax compliance certificates | | **Regulatory documents** | Licenses, permits, regulatory approvals | | **Custom documents** | Any additional documents required by your compliance process | ## Document workflow Based on your workflow configuration, Didit automatically identifies which documents are needed for the business verification. Required document types are presented to the business for upload. Documents are uploaded through the hosted verification flow or via the Business Console. Supported formats include PDF, JPG, PNG, and WebP. Didit extracts structured data from uploaded documents using OCR: * Company name and registration number from certificates * Address data from utility bills * Financial figures from statements * Names and roles from shareholder registers Extracted data is cross-referenced against: * Registry data from the company lookup * Information provided at session creation * Data from other uploaded documents Inconsistencies are flagged for analyst review. Analysts review uploaded documents in the console, verify their authenticity, and approve or reject each document individually. ## Analyst document requests During the review process, analysts can request additional documents: 1. Navigate to the business session in the console 2. Click **Request document** and specify the document type and description 3. The business is notified and can upload the requested document 4. The document appears in the session with a **Requested** status until uploaded This allows analysts to gather additional evidence without rejecting the entire business session. ## Document statuses Each document and the aggregate `document_verifications[]` check use the standard KYB feature status set: | Status | Description | | ----------------- | ------------------------------------------------------------------------------------------------------------- | | `NOT_FINISHED` | Document is still being processed (upload in progress, OCR running, or cross-check pending). | | `APPROVED` | Document was reviewed and accepted. | | `DECLINED` | Document was reviewed and rejected. | | `IN_REVIEW` | Document requires manual analyst attention. | | `RESUB_REQUESTED` | Analyst requested a resubmission — the business must re-upload this document before the session can progress. | ## Cross-check results When a document is processed, Didit cross-references the OCR-extracted data against the **user-provided data** submitted in the Key People flow (and any data confirmed during registry review) plus other uploaded documents. The cross-check produces structured results: | Category | Description | | ----------------------- | -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | | **Critical fields** | Fields where the document data and the user-provided data do not match — these require analyst review. Each field shows the document value, the user-provided value, and a confidence score. | | **Non-critical fields** | Fields with minor discrepancies or formatting differences that may not require action (e.g. abbreviation differences in company name). | | **People overlap** | Analysis of people mentioned in the document vs. people submitted by the user — highlights missing or additional individuals. | Cross-check results are displayed in the [Business Console](/business-verification/console) alongside the document preview, giving analysts a clear view of what matches and what needs attention. ## Retrieving documents via API Documents are attached to the Business Verification (KYB) session. Fetch them via the session decision: ```bash theme={null} curl https://verification.didit.me/v3/session/{session_id}/decision/ \ -H "x-api-key: YOUR_API_KEY" ``` The response includes a `document_verifications[]` array — each item has a `status`, `node_id`, `items[]` (each with a signed `file_url` and OCR extract), `groups`, and `required_groups`. See [response schema](/business-verification/response-schema#document_verifications) for the full structure. ## Next steps Where documents appear in the payload. Reviewing documents as an analyst. # KYB Integration Guide Source: https://docs.didit.me/business-verification/integration-guide Production-ready KYB integration: architecture, sessions, hosted flows, webhooks, polling, and decisions. From $2.00 per check, priced per country and tier. This guide is the companion to the [quickstart](/business-verification/quickstart). It covers the architecture, every integration decision, and the operational patterns that make KYB reliable in production. ## Architecture ```mermaid theme={null} sequenceDiagram participant You as Your platform participant Didit as Didit API participant Biz as Business contact participant Webhook as Your webhook endpoint You->>Didit: POST /v3/session/ (workflow_id, vendor_data) Didit-->>You: session_id, url, token You->>Biz: Deliver hosted verification URL (your email/flow) Biz->>Didit: Completes KYB hosted flow Didit->>Didit: Registry lookup, AML screening, OCR Didit->>Webhook: status.updated (session_kind: business) You->>Didit: GET /v3/session/{id}/decision/ Didit-->>You: Full KYB decision payload You->>You: Onboard / reject / escalate based on status ``` ## Authentication All requests require the `x-api-key` header with your application's API key. See [API authentication](/getting-started/api-authentication) for key rotation, environment separation, and scopes. ## Session creation Single endpoint: `POST /v3/session/`. The workflow's type determines whether the session is KYC or KYB — no explicit "business" flag is needed. **Recommended fields on creation:** | Field | Purpose | | ------------------ | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | | `workflow_id` | Required — references your KYB workflow. | | `vendor_data` | Your identifier for the business. Binds the session to a [Business entity](/entities/businesses/overview). | | `callback_url` | Optional — where to redirect the user after completion. | | `expected_details` | Optional — `{ company_name, registry_country, registration_number }`. Pre-fills the company registry search: the country of incorporation is pre-selected and locked (`registry_country` as `XX`, or `XX-YY` for state-level registries, e.g. `US-CA`), the company-name and registration-number fields are pre-filled, and the asserted search runs automatically — combining both identifiers when both are present. Prefill only — mismatches do not produce warnings. | | `metadata` | Optional JSON attached to the session. | Full schema: [create session](/sessions-api/create-session). ## Delivering the hosted link The response `url` is a hosted verification link. Options for delivery: * Email it from your own platform. * Embed it in your onboarding UI as a link. * Open it in an in-app webview (iOS / Android / React Native). You can **customize** the hosted experience — logo, color, domain, email templates — via [White-label](/console/white-label). ## Polling vs webhooks Webhooks are the recommended pattern. Didit POSTs completion events to your subscribed endpoint as soon as processing finishes. Polling is supported for development or when your webhook endpoint is unreachable: * Poll `GET /v3/session/{id}/decision/` with exponential backoff (every 10s initially, up to 60s). * Stop polling when `status` is one of `APPROVED`, `DECLINED`, `IN_REVIEW`. Polling at high frequency may hit [rate limits](/integration/rate-limiting). Always prefer webhooks in production. ## Webhook handling Subscribe to the events you care about — the same events cover both KYC and KYB, with `session_kind: "business"` inside the payload to identify business-session events: * `status.updated` — session status changed. Filter on `data.session_kind === "business"` for KYB sessions. * `data.updated` — session data changed (registry refresh, key-people submission, documents, ongoing AML). Same `session_kind` filter applies. * `business.status.updated` / `business.data.updated` — the linked [Business entity](/entities/businesses/overview) changed. Full event catalog: [KYB webhooks](/business-verification/webhooks). Signature verification and retry semantics: [webhooks reference](/integration/webhooks). ## Handling decisions ```typescript theme={null} switch (decision.status) { case 'APPROVED': await onboardBusiness(decision); break; case 'DECLINED': await logRejection(decision.decision_reason_code, decision); break; case 'IN_REVIEW': // Wait for analyst decision — another webhook will fire await markPending(decision); break; case 'RESUBMITTED': // The business was asked to re-upload a document await notifyBusiness(decision); break; } ``` See [KYB statuses](/business-verification/statuses) for the full state machine and reason codes. ## Resubmission flow When a Business Verification (KYB) session transitions to `RESUB_REQUESTED` (or a feature is marked for resubmission), the business needs to upload corrected or additional data. You can: * **Re-deliver** the same `url` — the hosted flow picks up where resubmission is needed. * **Open a [case](/transaction-monitoring/cases)** in the Business Console to track the back-and-forth internally. ## Business profile aggregation If you pass `vendor_data` on session creation, Didit aggregates all sessions for that business into a single [Business entity](/entities/businesses/overview). Use the entity's `features` map to answer "is this business fully verified right now?" without iterating sessions. Benefits: * Periodic re-KYB flows append to the same profile. * Transactions monitored against the same `vendor_data` carry the business's risk context. * UBOs and officers linked to User entities populate cross-entity relationships. ## Best practices | Practice | Why | | ----------------------------------- | ----------------------------------------------------------------- | | Always pass `vendor_data` | Without it, the session is orphaned and can't be aggregated. | | Use webhooks, not polling | Lower latency, no rate limit pressure. | | Verify webhook signatures | Prevents spoofed events. | | Store the `session_id` on your side | Needed to retrieve the decision and generate PDFs. | | Tag sessions with `metadata` | Simplifies reporting and debugging. | | Set up a test workflow | Use a sandbox workflow for integration testing before production. | ## Error handling | Scenario | Response | | ---------------------------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | | Invalid `workflow_id` | `400 Bad Request` | | Duplicate session with same `vendor_data` | Creates a new session — that's by design, since re-verification is expected. | | Dangerous country | Session is created but immediately `DECLINED` with reason `blocked_country`. | | Blocklisted `vendor_data` | Session auto-declined with reason `blocked_business`. | | Registry provider outage during company search | `POST /v3/kyb/search/` returns `502` with `code: "kyb_registry_provider_unavailable"`. Not billed - retry, or branch on `code` to offer manual company entry. In Didit's hosted flow, the business is routed into manual entry automatically instead of a retry-only error. See [KYB Registry Search](/standalone-apis/kyb-registry-search#provider-outages). | | Rate limit | `429 Too Many Requests` with `Retry-After` header. | Full [rate limiting](/integration/rate-limiting) reference. ## Next steps Every KYB event and payload. State machine reference. Decoding the KYB decision. # Key People Source: https://docs.didit.me/business-verification/key-people Verify UBOs, shareholders, directors, and officers in one unified KYB flow with role-aware checks and linked KYC sessions. From $2.00 per check, priced per country and tier, no contracts. **Key people** is Didit's unified model for every natural person and corporate entity tied to the business you're verifying: UBOs, shareholders (individual and corporate), directors, representatives, and other officer roles. A single Key People flow covers the lot — with role-aware verification dispatch and full side-by-side comparison between registry-sourced and user-submitted parties. For the Business-entity view of key people — how officers and UBOs aggregate across sessions — see [Businesses → Key people](/entities/businesses/key-people). ## How it works If the workflow enables registry prefill, the Key People screen is pre-populated with UBOs, shareholders and officers extracted from the registry check. The end user can edit, add, or remove parties before submitting. The end user submits the final list of key people through the hosted verification flow. You don't call this step yourself — it happens inside the KYB flow whose URL you delivered from [Create Session](/sessions-api/create-session). For each submitted party, Didit checks the role's configured verification settings: * Applies the workflow's ownership threshold — UBOs and shareholders below the configured percentage don't require individual verification. * Honours the "skip verification" flag the end user set, if the role allows skipping. * Spawns a child User Verification (KYC) session for person parties that require KYC. * Spawns a child KYB sub-session for corporate UBOs when nested KYB is enabled on the workflow. The Key People feature status becomes `Awaiting User` while any required child session is still in progress. When every child session finishes, the status aggregates to `Approved`, `Declined`, or `In Review` based on the outcomes. ## Roles collected Key people can carry one or more of the following roles — a single person can hold several at once (for example, director **and** shareholder). The full taxonomy: | Category | Roles | | ------------------------------- | -------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | | **Ownership** | `ubo`, `shareholder`, `beneficiary`, `settlor`, `protector`, `investor` | | **Governance / representation** | `director`, `non_executive_director`, `chairman`, `secretary`, `representative`, `authorized_signatory`, `trustee`, `company_officer`, `founder`, `legal_advisor`, `other` | Every role can be individually configured in the workflow — enabled or disabled, required or optional for KYC, mapped to a specific KYC workflow, and optionally skippable. See [Ownership](/business-verification/ownership) for the verification dispatch details. ## Data collected per key person The hosted flow asks for a default set of fields and additional workflow-configured custom fields. See [Ownership → Fields collected](/business-verification/ownership#data-collected-for-each-key-person) for the full list. ## Registry confirmation Before the Key People step, the end user reviews the company data extracted from the registry check and optionally edits any fields. The hosted flow then stores: * The **raw registry payload** as an immutable audit record (`registry_data`). * The **user-confirmed data** (`user_provided_data`) with a timestamp that marks when the user confirmed. * A merged canonical view on the top-level company fields — user-confirmed when present, registry fallback otherwise. See [Company data → Registry vs user-provided data](/business-verification/company-data#registry-data-vs-user-provided-data) for the full model. ## Shape in the decision response After submission, the collected key people surface in the KYB decision under `key_people_checks[]`, split into two buckets — **registry** (what the provider disclosed) and **submitted** (what the business admin confirmed through the flow) — plus a `ubo_kyc_summary` that rolls up UBO KYC progress. See the full [key\_people\_checks reference](/business-verification/response-schema#key_people_checks). ## Resubmit behaviour * **Key People** and **Registry Check** cannot be resubmitted directly. To re-verify a specific person, resubmit their individual child KYC session. * When a child KYC session is resubmitted, the parent Key People feature status automatically returns to `Awaiting User`. * When the resubmitted child finishes, the parent re-aggregates based on all child statuses. ## Configuration options All Key People behaviour is configured per workflow from the Business Console: | Setting | What it controls | | ----------------------------------- | ----------------------------------------------------------------------------------------------------------- | | **Registry prefill** | Pre-populate the Key People form from registry data | | **Extra fields — persons** | Custom fields to collect for each person party | | **Extra fields — companies** | Custom fields to collect for each corporate party | | **UBO ownership threshold** | Minimum ownership percentage to classify someone as a UBO | | **Shareholder ownership threshold** | Minimum ownership percentage to classify someone as a shareholder | | **Per-role settings** | For each role: enabled/disabled, require KYC, KYC workflow to use, skippable | | **Corporate UBO nested KYB** | When enabled, corporate UBOs trigger their own child KYB session | | **Reuse verified individuals** | See [Reusing verified individuals across KYB checks](#reusing-verified-individuals-across-kyb-checks) below | | **Notify parties by email** | Automatically email each key person with their verification link | Configure at *Workflows → \[KYB workflow] → Key People* in the console. ## Reusing verified individuals across KYB checks When **Reuse verified individuals** is enabled on a workflow (the default), a key person doesn't have to redo KYC every time they show up on a new KYB check. Didit looks for an existing approved KYC from a previous KYB check and links it to the new party instead of spawning a fresh child KYC session. This is a distinct mechanism from [Reusable KYC](/core-technology/reusable-kyc/overview), which lets an *end user* voluntarily carry one finished session across separate Didit-integrated applications via a share/import token. The KYB reuse setting on this page is automatic, workflow-configured, and scoped to key people within a single application - no share token, and no action from the end user. **Matching.** A candidate match is found by comparing the submitted person's full name (case-insensitive, whitespace-trimmed) against key people from the application's other KYB checks. There's no additional matching signal - a document number, email, or phone match is not required or checked. A name entered with different spelling, a middle name, or a transliteration won't match, and in rare cases two different people who share a name could match; review your Key People results with this in mind. **Scope.** Matching looks across every other KYB check that belongs to the *same application*, not just the current KYB check and not other applications in your organization. A person verified as a UBO on Company A can be matched when they later appear as a director on Company B, as long as both checks run under the same application. **Eligible statuses.** Only a party's most recent **Approved** KYC is eligible for reuse. A **Declined** KYC for that name blocks reuse entirely - the party is flagged and a fresh KYC is requested instead of falling back to the declined one. A KYC that's still **In Review** is never considered a candidate. **Retention.** Matching only considers KYC sessions created in roughly the last year that haven't been deleted. If the only matching session falls outside that window, or the person or org has deleted it, the check finds no eligible match and silently requests a new KYC - it never fails or blocks Key People submission. **Billing.** A reused KYC is not billed again. Linking an already-approved session to the new party carries no additional charge; you're only billed once, on the original KYC. ```txt Example theme={null} Company A: Jane Doe submitted as UBO, KYC approved. Company B (same application): Jane Doe submitted as a director. "Reuse verified individuals" is enabled, so Company B's Key People check links Jane's existing approved KYC instead of requesting a new one - free, and instantly Approved for that party. ``` ## Next steps Fields collected, custom data, and registry vs submitted reconciliation. Governance roles within the key-people model. `key_people_checks[]` field-by-field reference. # Officers & Representatives Source: https://docs.didit.me/business-verification/officers Verify directors, officers, and authorized representatives via Didit's unified Key People model with multi-role tagging and AML screening. From $2.00 per check, priced per country and tier. Officers, directors, and representatives are **not a separate concept in Didit's KYB model** — they live inside [Key People](/business-verification/key-people) alongside UBOs and shareholders, tagged with one or more roles per person. A single person can be a director **and** a shareholder, or a representative **and** an authorized signatory — the party carries the full role list, not just one role. ## Full role taxonomy Every key person can hold one or more of these roles: ### Governance / representation | Role | Description | | ------------------------ | --------------------------------------------------------------- | | `director` | Board member with governance responsibilities | | `non_executive_director` | Board member without day-to-day management duties | | `chairman` | Chair of the board | | `secretary` | Company secretary handling administrative and compliance duties | | `representative` | Legal or appointed representative of the company | | `authorized_signatory` | Person empowered to sign on behalf of the company | | `trustee` | Trustee of a structure holding company interests | | `company_officer` | General officer role | | `founder` | Founding member of the company | | `legal_advisor` | Retained legal counsel for the company | | `other` | Any role outside the standard taxonomy | ### Ownership / beneficiary | Role | Description | | ------------- | ---------------------------------------------------------------------------------- | | `ubo` | Ultimate Beneficial Owner — individual who ultimately owns or controls the company | | `shareholder` | Registered shareholder (individual or corporate) | | `beneficiary` | Beneficiary of a trust or similar structure | | `settlor` | Settlor of a trust | | `protector` | Protector of a trust | | `investor` | Investor role (outside formal share ownership structures) | A single person can carry both categories — for example, a founder who is also a director and a UBO holds three roles on the same key-people record. ## Multi-role records Each key person record includes a list of roles, each with its own ownership/voting percentages where relevant. This is how a director-plus-shareholder looks in the response: ```json theme={null} { "uuid": "...", "name": "Jane Doe", "first_name": "John", "last_name": "Doe", "entity_type": "person", "roles": [ { "role": "director", "ownership_percent": null, "voting_percent": null }, { "role": "shareholder", "ownership_percent": 15.0, "voting_percent": 15.0 } ], "kyc_status": "Approved", "kyc_session_url": "https://verify.didit.me/..." } ``` ## KYC linking Every key person can be linked to an individual User Verification (KYC) session. The linking happens automatically when the role's workflow settings require KYC — the system spawns the child KYC session, emails the person their verification link (if that option is enabled), and tracks status back on the party. See [Ownership → How role settings drive verification](/business-verification/ownership#how-role-settings-drive-verification) for the full routing logic. For the B2C-safe KYC status values surfaced on each party (`Approved`, `Declined`, `Pending`), see the [response schema](/business-verification/response-schema#company-block). ## AML screening Every identified key person is automatically screened against global AML watchlists as part of the business verification process. PEP matches are especially relevant for governance roles — directors and signatories of regulated companies often surface on PEP lists. See [Business AML screening](/business-verification/aml). ## Requires-verification flag Each party carries a `requires_verification` flag that tells you whether the workflow demands KYC for that person: | Value | Meaning | | ------- | ----------------------------------------------------------------------- | | `true` | KYC must complete for this person before the session can approve. | | `false` | Person is identified and AML-screened but does not need individual KYC. | Configure which roles require verification from *Workflows → \[KYB workflow] → Key People → per-role settings*. Typical defaults: * Directors and UBOs above the workflow's threshold → `requires_verification: true`. * Authorized signatories and secretaries → optional. * Non-executive board members → optional. ## Skipping a key person If a person cannot be verified (deceased, unreachable, historical), they can be marked with `is_skipped: true` — either by the end user in the hosted flow (if the role's settings allow skipping) or by an analyst from the console. Skipped parties are excluded from the verification gate but still surface in the response for audit. ## Cross-referencing across sources Data about each key person can come from three places, and the console shows all three side-by-side: * **Registry records** — what the official registry disclosed. * **User-submitted** — what the business admin confirmed or added in the Key People flow. * **Uploaded documents** — names extracted via OCR from articles of association, shareholder registers, or power-of-attorney documents. Inconsistencies surface as warnings on the session decision. ## Effect on the Business entity Linking a key person to a User entity via KYC creates a lasting relationship on the [Business entity](/entities/businesses/overview). You can then: * See every business each person serves in a governance or ownership role. * Propagate a User's status changes (flagged, blocked) into businesses where they serve as a key person. * Run ongoing AML monitoring on each linked person independent of any specific KYB session. ## Next steps The full Key People flow. UBO identification and ownership chains. Company and person AML screening. # Business Verification Source: https://docs.didit.me/business-verification/overview Verify companies and legal entities with automated registry lookups, UBO identification, officer screening, and AML — from $2.00 per check, priced per country and tier, no contracts. This Didit Academy lesson follows a business verification from start to finish: the KYB dashboard, the registry check, shareholders and UBOs, AML screening, and what the company representative sees on their side. Didit's Business Verification (KYB) lets you verify companies and legal entities before onboarding them to your platform. The system automates company registry lookups, identifies beneficial owners and officers, screens all parties against AML watchlists, and collects supporting documents — all within a single workflow. Each verified company is tracked as a [business profile](/business-verification/business-profiles), aggregating results across sessions. New to Didit KYB? Start with the [quickstart](/business-verification/quickstart) for a 10-minute end-to-end walkthrough, then read the [integration guide](/business-verification/integration-guide) for production patterns. For the underlying Business entity model (linking to Users, blocklists, import/export), see [Businesses](/entities/businesses/overview). ## How it works Start a business verification by creating a session with a **KYB workflow**. When the workflow type is KYB, Didit automatically creates a business session: ```bash theme={null} curl -X POST https://verification.didit.me/v3/session/ \ -H "x-api-key: YOUR_API_KEY" \ -H "Content-Type: application/json" \ -d '{ "workflow_id": "your-kyb-workflow-id", "vendor_data": "company-123" }' ``` The session type is determined by the workflow — no extra fields needed. KYB workflows automatically create business sessions with business-specific features enabled. Didit queries official company registries at the **Lite**, **Shareholders**, or **UBOs** tier — each priced per country, see [registry pricing](/getting-started/kyb-registry-pricing). Lite retrieves: | Data | Description | | ----------------------- | ------------------------------------------- | | **Company name** | Legal name as registered | | **Registration number** | Official company registration number | | **Country** | Country of incorporation | | **Status** | Active, dissolved, struck off, etc. | | **Company type** | Ltd, LLC, PLC, SA, GmbH, etc. | | **Incorporation date** | Date the company was registered | | **Registered address** | Official registered office address | | **Tax number** | Tax identification number (where available) | Registry data is cross-referenced with the information provided to detect inconsistencies. The system identifies every person and corporate entity tied to the business under the unified **Key People** model: * **UBOs** — individuals who ultimately own or control the company, with ownership and voting percentages * **Shareholders** (individual and corporate) — each with their ownership percentage * **Directors, representatives, secretaries, authorized signatories, and other officer roles** — with their specific role tag * **Corporate ownership layers** — parent companies in the ownership chain, with optional nested KYB A single person can carry multiple role tags (for example, director **and** shareholder). Each role is individually configured in the workflow — which roles require KYC, which KYC workflow to use, and whether the end user can skip verification. Learn more in [Key People](/business-verification/key-people) and [Ownership](/business-verification/ownership). All identified parties are automatically screened against global AML watchlists: * **Company AML** — screens the company entity against sanctions, adverse media, and regulatory enforcement lists * **Person AML** — screens each key person (UBO, shareholder, director, representative, etc.) individually * Uses the same [two-score risk system](/core-technology/aml-screening/overview) (match score + risk score) as user verification Collect and verify supporting documents: | Document type | Examples | | -------------------------------- | ------------------------------------------------------------ | | **Certificate of incorporation** | Company formation certificate | | **Articles of association** | Bylaws, memorandum of association | | **Proof of address** | Utility bills, bank statements for the registered address | | **Shareholder register** | Official register of shareholders | | **Financial statements** | Annual accounts, audit reports | | **Tax certificates** | Tax registration or compliance certificates | | **Custom documents** | Any additional documents required by your compliance process | Analysts can request additional documents from the business during the review process. The business session receives an overall status based on all checks: | Status | Meaning | | ------------- | -------------------------------------------------------------------- | | **Approved** | All checks passed — company is verified | | **In Review** | One or more checks require manual review | | **Declined** | A critical check failed (e.g., dissolved company, sanctioned entity) | Analysts can review all collected data in the Business Console, add comments, request additional documents, and make a final decision. ## Business session lifecycle Each business verification runs within a **business session** that tracks progress through the following statuses: | Status | Description | | ------------- | ---------------------------------------------------------------------------------------------- | | `NOT_STARTED` | Session created but verification has not begun | | `IN_PROGRESS` | Verification is underway — registry lookups, AML screening, or document collection in progress | | `APPROVED` | All checks passed — company is verified | | `DECLINED` | A critical check failed (e.g., dissolved company, sanctioned entity) | | `IN_REVIEW` | One or more checks require manual analyst review | | `RESUBMITTED` | Previously declined session resubmitted with updated data | Each session has a unique `session_id`, a sequential `session_number`, and a `session_token` for the hosted verification link. When a session is created with a `vendor_data` identifier, Didit automatically links it to the corresponding [business profile](/business-verification/business-profiles). ## Feature statuses Business verification tracks the status of each component independently: | Feature | Description | | ------------------ | ------------------------------------------------------------ | | **Registry check** | Company registry lookup and data extraction | | **Company AML** | Company-level AML screening against sanctions and watchlists | | **Documents** | Document collection, OCR, and cross-referencing | | **Key people** | Beneficial owner and officer identification, AML, and KYC | Each feature can be: `NOT_FINISHED`, `APPROVED`, `DECLINED`, `IN_REVIEW`, or `RESUB_REQUESTED`. The overall session status aggregates the individual feature statuses — the session is only `APPROVED` when all required features pass. ## Webhook events Business sessions generate the following webhook events: | Event | Trigger | | ------------------------- | ---------------------------------------------------------------------------------------------------------------- | | `status.updated` | Session status changed. Payload carries `session_kind: "business"` for KYB sessions. | | `data.updated` | Session data changed (registry, key people, documents, AML). Payload carries `session_kind: "business"`. | | `business.status.updated` | The linked [Business entity](/entities/businesses/overview)'s status changed (`ACTIVE` / `FLAGGED` / `BLOCKED`). | | `business.data.updated` | The linked Business entity's profile fields or aggregate counters changed. | Webhook payloads include `session_kind: "business"` and the `business_session_id` to distinguish them from user verification events. See [Webhooks](/integration/webhooks) for signature verification and delivery details. ## Key capabilities | Capability | Description | | ------------------------------ | ------------------------------------------------------------------------------------------------------------------------------------------------------------- | | **Automated registry lookups** | Query official company registries in supported countries at the Lite, Shareholders, or UBOs tier, [priced per country](/getting-started/kyb-registry-pricing) | | **UBO identification** | Automatically extract beneficial ownership structures with percentages | | **Officer screening** | Identify and verify directors, secretaries, and other officers | | **Company AML** | Screen the company entity against sanctions and watchlists | | **Person AML** | Screen all identified UBOs and officers individually | | **KYC linking** | Link each identified person to a User Verification (KYC) session for identity verification | | **Document collection** | Structured document requests with upload tracking | | **OCR cross-checking** | Extract data from uploaded documents and cross-reference with registry data | | **Business profiles** | Automatic profile creation and session aggregation for each verified company | | **Feature-level statuses** | Independent status tracking for registry, AML, documents, and key people | | **Risk assessment** | Overall risk level based on company status, AML results, and ownership complexity | | **Webhooks** | Receive session lifecycle and data update events in real time via [webhooks](/integration/webhooks) | ## Business sessions vs. user sessions | Feature | User session | Business session | | --------------------- | ----------------------------------- | ------------------------------------------------------------ | | **Target** | Individual person | Company or legal entity | | **Session kind** | `user` (default) | `business` | | **Core checks** | ID, liveness, face match, AML | Registry lookup, UBO, officers, company AML | | **Additional checks** | Phone, email, proof of address, NFC | Document collection, person AML, KYC linking | | **Webhook payloads** | Standard session events | Include `session_kind: "business"` and `business_session_id` | ## Next steps Track companies across sessions with profiles, tags, and bulk operations. Registry lookups, company status, and data cross-referencing. UBO identification, corporate shareholders, and ownership chains. Director identification, roles, and KYC linking. Company and person-level AML checks. Document collection, requests, and OCR verification. # Ownership & UBO Source: https://docs.didit.me/business-verification/ownership Extract Ultimate Beneficial Owners (UBOs) from company registries with ownership chains, percentages, and automated AML screening. From $2.00 per check, priced per country and tier. Identifying who ultimately owns and controls a company is the heart of KYB. Didit pulls the ownership structure from the registry where available, lets the business admin confirm and extend it in the hosted flow, and then runs role-aware verification on each key person. ## Beneficial owners (UBOs) An **Ultimate Beneficial Owner (UBO)** is a natural person who ultimately owns or controls a legal entity. UBOs surface in the session decision under `key_people_checks[].registry.beneficial_owners[]` (registry-derived) and `key_people_checks[].submitted.parties[]` (user-submitted), with any other role such as shareholder or director in the same list. ## Data collected for each key person The hosted flow collects a default set of fields plus any workflow-configured custom fields. The defaults: | Field | Person | Company | | ------------------------------------------------- | :--------: | :-------------------------: | | `name` or `first_name` + `last_name` | ✅ required | ✅ required (`company_name`) | | `email` | ✅ required | ✅ required | | `nationality` / country | ✅ required | ✅ required | | `role` (one or more per party) | ✅ required | ✅ required | | `ownership_percent` / `voting_percent` (per role) | optional | optional | | `date_of_birth` | optional | — | | `phone_number` | optional | — | | `position` (free-text job title) | optional | — | | `registration_number` | — | optional | | `entity_type` | `person` | `company` | `entity_type` is set automatically based on whether the party is a natural person or a corporate entity. ### Custom fields Workflows can require additional fields per person or per company — any number of them. They're configured in the Business Console on the KYB workflow and end up in the `custom_fields` object on each party in the decision response. Use custom fields for things like source-of-wealth declarations, tax residency, internal client IDs, or industry-specific disclosures. ## Corporate shareholders and nested ownership When a shareholder is itself a company (not a natural person), Didit records: * Company name and registration number. * Ownership percentage held by that corporate shareholder. * Country of incorporation. This lets you trace the chain through multiple layers to the ultimate natural persons. ### Nested KYB for corporate UBOs When the workflow enables nested KYB for corporate UBOs, each corporate party triggers its own child KYB sub-session — the company verifies under the same process you run at the top level, and its result feeds back into the parent. Off by default; opt in per workflow. ## Ownership thresholds Most jurisdictions classify UBOs at **25% or more**. The threshold is configurable per workflow: | Jurisdiction | Typical UBO threshold | | ------------ | ------------------------------------ | | EU (AMLD) | 25% ownership or control | | UK | 25% shares or voting rights | | USA (CTA) | 25% ownership or substantial control | | Singapore | 25% shares or voting power | Set it from *Workflows → \[KYB workflow] → Risk → UBO threshold*. Your workflow can also flag or route for review when no UBO meets the threshold (common with widely-held public companies). ## Voting vs economic rights Ownership disclosures distinguish two kinds of control: | Right | What it means | | -------------------------- | ------------------------------------------------------- | | **Economic (ownership) %** | Share of the company's economic value / dividend rights | | **Voting %** | Share of voting power on shareholder resolutions | These are usually equal but can diverge when a company issues dual-class shares or preferred equity. Didit records both. Rules and thresholds can check either — most jurisdictions require UBO disclosure when *either* crosses 25%. ## Effective ownership through a chain When ownership runs through a corporate shareholder, effective ownership of a downstream natural person is computed by multiplying percentages along the chain. ### Example — 3-layer chain ``` Acme Corp (target) └─ 60% → Acme Holdings Ltd └─ 75% → Jane Doe (natural person) └─ 40% → John Smith (natural person) ``` Computed UBOs: * **Jane Doe** — effective ownership of Acme Corp = 60% × 75% = **45%** (UBO). * **John Smith** — effective ownership of Acme Corp = **40%** (UBO). With a 25% UBO threshold, both Jane and John are disclosed. With a 50% threshold, no UBO meets the cut — Didit flags this as a transparency concern. ## How role settings drive verification Each role is individually configured per KYB workflow: enabled or disabled, whether it requires KYC, which KYC workflow to use for that role, and whether the end user can choose to skip it. When a key person is submitted: 1. Didit checks the submitted party's roles against the workflow's role settings. 2. For roles marked as requiring verification, a child verification session is started: * **Person parties** → child User Verification (KYC) session, using either the role-specific KYC workflow or the default. * **Corporate UBOs** (when nested KYB is enabled) → child Business Verification (KYB) sub-session. 3. For roles marked as skippable, the end user sees a "skip verification" option and can opt out; skipped parties are recorded but don't block the parent session. 4. Parties below the workflow's ownership threshold don't trigger individual verification even if the role would otherwise require it. Configure everything from *Workflows → \[KYB workflow] → Key People* in the Business Console. ## Monitoring shareholders and UBOs Registry monitoring is **coming soon**. No country in the staging retail catalog checked on September 7, 2026 has monitoring enabled. The configured rate is USD 2.00 per company per year; a price does not mean the feature is available. The behavior below describes the planned service after rollout. A company verified at the **Shareholders** or **UBO** tier can be kept under **continuous registry monitoring**. The registry pushes changes of company status, officers, ownership and registered address; on each change Didit: * moves the business session from *Approved* back to *In Review*, with the change recorded on the session; * fires the `kyb_registry_change` [business webhook](/business-verification/webhooks) with the fields that changed; * keeps the company's registry record current. Monitoring is **only available where the country allows it**: the registry provider must offer a watch for that jurisdiction. The full list is the [continuous monitoring countries table](/business-verification/supported-countries#continuous-registry-monitoring); a company verified at the Lite tier, or in a country outside that list, is not enrolled and the business page shows why. Enable it per workflow from *Workflows → KYB Registry Check → Advanced → Continuous registry monitoring*. It costs **\$2.00 per company per year**, billed on enrolment and on each yearly renewal; when the wallet cannot cover a renewal, monitoring stops for that company instead of running unpaid. Cancel it at any time from the business page (*KYB Registry Check → Registry monitoring*). ## Registry vs user-submitted reconciliation The response surfaces both sources side-by-side under `key_people_checks[]`: * `registry.officers[]` and `registry.beneficial_owners[]` — what the provider disclosed. * `submitted.parties[]` — what the business admin explicitly submitted through the flow, with `source: "USER"`. Analysts compare the two buckets visually in the console to spot missing UBOs, extra undisclosed parties, or ownership percentages that don't line up. There's no automated diff endpoint — you can reconcile on your side by matching on name, role, and ownership where applicable. ## AML screening Every identified key person is automatically screened against global AML watchlists, both from the registry side and the submitted side. See [Business AML screening](/business-verification/aml) for how company-level and person-level AML checks combine. ## Next steps The Key People flow end-to-end. Governance roles inside the key-people model. How ownership complexity rolls into risk level. # KYB quickstart: business verification in 10 minutes Source: https://docs.didit.me/business-verification/quickstart Verify a business end-to-end in under 10 minutes — registry lookup, UBO, officers, AML, and webhooks. From $2.00 per check, priced per country and tier, no contracts. This guide walks you through a complete KYB verification in under 10 minutes. You'll create a workflow, start a session, deliver the hosted verification link to your business contact, wait for the webhook, and fetch the final decision. ## Prerequisites * A Didit application with KYB enabled. Create one at [business.didit.me](https://business.didit.me) if needed. * An API key from *Developer Settings → API Keys*. * A webhook endpoint reachable from the internet (for the decision webhook). ## Steps Navigate to *Workflows → Create workflow*. Choose **Business Verification** as the workflow type. Enable the features you need: * **Company registry lookup** (required) * **Company AML** (recommended) * **Key People** (required for most regulated industries) * **Documents** (optional — pick document types you'll require) Save and copy the `workflow_id` — you'll use it in the next step. ```bash theme={null} curl -X POST https://verification.didit.me/v3/session/ \ -H "x-api-key: YOUR_API_KEY" \ -H "Content-Type: application/json" \ -d '{ "workflow_id": "YOUR_KYB_WORKFLOW_ID", "vendor_data": "biz-acme-001" }' ``` The response contains the `session_id`, `session_number`, and `url` — the hosted verification link you deliver to the business contact. The workflow's type (KYB) automatically flags the session as a business session. Deliver the `url` to the company admin via your own email or chat. They open it, fill in the registry data, add key people and UBOs, and upload documents. You can customize the hosted experience with branding, logo, and domain — see [White-label](/console/white-label). When the business finishes the flow and KYB processing reaches a terminal status, Didit POSTs a `status.updated` event to your webhook endpoint. Business-session events carry `session_kind: "business"` inside `data` — filter on that to route the event to your KYB handler. Verify the `X-Signature-V2` HMAC signature before trusting the event (see [webhooks](/integration/webhooks)), then trigger your downstream logic. Store the destination's `secret_shared_key` (returned when you register the webhook) as `DIDIT_WEBHOOK_SECRET` in your `.env`. Example payload: ```json theme={null} { "event": "status.updated", "application_id": "app_abc123", "timestamp": "2026-04-18T12:30:00Z", "data": { "session_id": "bs_01H...", "session_kind": "business", "vendor_data": "biz-acme-001", "status": "APPROVED", "previous_status": "IN_PROGRESS" } } ``` The `status.updated` webhook payload already contains the full decision. You only need to call this endpoint if you didn't subscribe to webhooks, or you want to fetch the decision on demand later. ```bash theme={null} curl https://verification.didit.me/v3/session/bs_01H.../decision/ \ -H "x-api-key: YOUR_API_KEY" ``` The decision includes registry data, key people (UBOs, shareholders, directors and representatives), AML hits, documents, and per-feature results. See [response schema](/business-verification/response-schema) for the full payload reference. Based on `status`: * `APPROVED` — onboard the business. * `DECLINED` — reject and log the reason code. * `IN_REVIEW` — wait for the analyst decision; you'll receive another webhook when it resolves. ## Node.js example ```typescript theme={null} import fetch from 'node-fetch'; const API_KEY = process.env.DIDIT_API_KEY!; const WORKFLOW_ID = process.env.DIDIT_KYB_WORKFLOW_ID!; const BASE_URL = 'https://verification.didit.me'; async function startKybVerification(vendorData: string) { const res = await fetch(`${BASE_URL}/v3/session/`, { method: 'POST', headers: { 'x-api-key': API_KEY, 'Content-Type': 'application/json', }, body: JSON.stringify({ workflow_id: WORKFLOW_ID, vendor_data: vendorData }), }); if (!res.ok) throw new Error(`Session create failed: ${res.status}`); return res.json(); } async function getDecision(sessionId: string) { const res = await fetch(`${BASE_URL}/v3/session/${sessionId}/decision/`, { headers: { 'x-api-key': API_KEY }, }); return res.json(); } // Kick off the flow const { session_id, url } = await startKybVerification('biz-acme-001'); console.log('Deliver this URL to your contact:', url); // ... later, after the webhook confirms completion: const decision = await getDecision(session_id); console.log('KYB status:', decision.status); ``` ## What happens automatically * Company registry lookup against 190+ jurisdictions. * UBO and officer extraction from registry data. * Company-level AML screening (sanctions, PEP, adverse media). * Person-level AML for each identified party. * Document OCR and cross-referencing. * [Business profile](/business-verification/business-profiles) creation and aggregation keyed by `vendor_data`. ## Next steps End-to-end architecture, polling vs webhooks, retry logic. Every KYB event and payload shape. Session, feature, and registry status reference. The full KYB decision payload. How profiles aggregate across sessions. # KYB Response Schema Source: https://docs.didit.me/business-verification/response-schema Annotated KYB decision payload: registry checks, key people, UBO KYC summaries, documents, AML screenings, and shared fields. From $2.00 per check, priced per country and tier. This page documents the full payload returned by [`GET /v3/session/{id}/decision/`](/sessions-api/retrieve-session) for a Business Verification (KYB) session. The endpoint is unified — when you pass a business `session_id`, the response carries `session_kind: "business"` and the business-specific feature arrays below. ## Top-level structure ```json theme={null} { "session_id": "bs_01H...", "session_kind": "business", "session_number": 89, "session_url": "https://verify.didit.me/...", "status": "APPROVED", "workflow_id": "wf_kyb_standard", "features": ["KYB_REGISTRY", "KYB_COMPANY_AML", "KYB_DOCUMENTS", "KYB_KEY_PEOPLE"], "vendor_data": "biz-acme-001", "metadata": { }, "callback": null, "registry_checks": [ ... ], "aml_screenings": [ ... ], "document_verifications": [ ... ], "key_people_checks": [ ... ], "phone_verifications": null, "email_verifications": null, "questionnaire_responses": null, "ip_analyses": null, "reviews": [ ], "contact_details": { ... }, "expected_details": null, "created_at": "...", "expires_at": "..." } ``` All feature arrays are multi-instance — each item represents one node in a graph workflow. Null means the feature was not present in this session's workflow. ## Shared top-level fields | Field | Type | Description | | -------------------------- | ---------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ | | `session_id` | UUID | Unique session identifier | | `session_kind` | enum | Always `"business"` for KYB sessions | | `session_number` | int | Sequential number within the application | | `session_url` | URL | Hosted verification link | | `status` | enum | Overall session status (see [statuses](/business-verification/statuses)) | | `workflow_id` | UUID | Workflow that drove this session | | `features` | array of strings | Feature identifiers the workflow ran (e.g. `KYB_REGISTRY`, `AML`, `KYB_DOCUMENTS`, `KYB_KEY_PEOPLE`, `PHONE`, `EMAIL`) | | `vendor_data` | string | Your identifier for the business | | `metadata` | object | Free-form JSON you attached at session creation | | `callback` | URL or null | Optional post-verification redirect URL | | `contact_details` | object or null | `{ email, email_lang, send_notification_emails, phone }` — set when the flow includes email/phone notifications | | `expected_details` | object or null | Business expected-data payload you passed on creation: `company_name`, `registry_country` (`XX` or `XX-YY` with the state for state-level registries, e.g. `US-CA`), `registration_number` | | `reviews` | array | Latest reviewer notes on the session | | `created_at`, `expires_at` | ISO timestamps | — | ## `registry_checks[]` Each item is one company registry check (typically one per session; multiple in graph workflows with recursive corporate UBO KYB). ```json theme={null} { "status": "Approved", "node_id": "feature_kyb_registry", "data_resolved": true, "company": { ...see below... }, "ownership_structure": { }, "warnings": [] } ``` | Field | Description | | --------------------- | --------------------------------------------------------------------------------------------------------------------------------------- | | `status` | Feature lifecycle status (`Approved`, `Declined`, `In Review`, `Not Finished`, `Resub Requested`) | | `node_id` | Graph node identifier for this check | | `data_resolved` | `true` when registry data has finished loading or the user provided the data manually | | `company` | Full registry payload — see **`company` block** below | | `ownership_structure` | Raw ownership-chain JSON as returned by the registry provider | | `warnings` | Structured warnings / log entries scoped to this registry check. See [Business Verification warnings](/business-verification/warnings). | ### `company` block The nested company object is the full view of the legal entity as derived from the registry (and optionally user-edited): ```json theme={null} { "uuid": "...", "node_id": "feature_kyb_registry", "status": "Approved", "registry_status": "active", "data_resolved": true, "company_name": "Acme Corporation Limited", "registration_number": "12345678", "country_code": "GBR", "company_type": "Private Limited", "incorporation_date": "2010-05-14", "registered_address": "1 Main Street, London EC1A 1AA, United Kingdom", "tax_number": "SAMPLE-TAX-12345", "risk_level": "LOW", "verification_status": "verified", "is_from_registry": true, "fetch_status": "resolved", "alternative_names": "Acme Ltd", "nature_of_business": "Software publishing", "registered_capital": "100000 GBP", "website": "https://acme.example", "email": "alex.sample@example.com", "phone": "+15550101000", "legal_entity_identifier": "529900XXXXXXXXXXXXX", "location_of_registration": "London", "vat_number": "GB123456789", "vat_validation_status": "not_applicable", "vat_validated_name": null, "vat_validated_address": null, "vat_checked_at": null, "financial_summary": { }, "officers": [ ... ], "beneficial_owners": [ ... ], "addresses": [ ... ], "industries": [ ... ], "accounts": { ... }, "registry_data": { }, "user_provided_data": { }, "confirmed_by_user_at": "2026-04-16T10:10:00Z", "last_console_edit_at": null, "is_editable": false } ``` | Field | Description | | ---------------------------------------------- | ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | | `registry_status` | Provider-reported status (`active`, `dissolved`, `struck_off`, `inactive`, etc.). See [statuses](/business-verification/statuses#registry-status-from-the-provider) | | `is_from_registry` | `true` when data came from an official registry; `false` for manual entry | | `fetch_status` | `pending`, `resolved`, or `failed` — registry lookup state | | `verification_status` | `verified`, `failed`, or `unknown` | | `is_editable` | `true` while registry-sourced data can still be edited by the end user | | `registry_data` / `user_provided_data` | Raw JSON for registry-returned vs user-entered fields (useful for audit diffing) | | `confirmed_by_user_at` | Timestamp when the end user confirmed / edited the registry data | | `vat_number` | VAT number as submitted, when collected | | `vat_validation_status` | Result of the EU VIES check: `valid`, `invalid`, `could_not_validate`, or `not_applicable` (non-EU companies, or no VAT number provided). See [VAT validation](/business-verification/company-data#vat-validation-vies) | | `vat_validated_name` / `vat_validated_address` | Trader name and address registered with VIES, when the member state discloses them | | `vat_checked_at` | Timestamp of the VIES check; `null` when no check ran | | `officers[]` | Officers with embedded KYC enrichment (see below) | | `beneficial_owners[]` | UBOs with embedded KYC enrichment (see below) | | `addresses`, `industries`, `accounts` | Extracted from `registry_data` when available | When reported, `industries` includes classification entries with `code` and `description`, and `addresses` includes entries with `address`, `type`, and `description`. `accounts` can include `last_annual_return_date` and `last_agm_date`; these describe corporate filings and meetings, not financial statements. Industry descriptions or a registry business scope populate `nature_of_business`. Contact details and alternative names are populated when available, while explicit user or reviewer edits take precedence. ### Officer item shape (inside `company.officers`) ```json theme={null} { "uuid": "...", "name": "Jane Doe", "first_name": "Jane", "last_name": "Doe", "date_of_birth": null, "date_of_birth_year": 1983, "date_of_birth_month": 2, "address": "1 Example Street, London", "appointment_date": "2024-07-01", "termination_date": null, "designation": "Director", "role": "director", "nationality": "USA", "is_active": true, "kyc_status": "Approved", "kyc_session_url": "https://verify.didit.me/..." } ``` `date_of_birth` is populated only when the registry supplies a complete date. If the registry reports only a year or month and year, use `date_of_birth_year` and `date_of_birth_month`; the missing day is never inferred. Names, birth details, address, and appointment dates remain available in both the company officer list and the Key People registry list. ### Beneficial owner item shape (inside `company.beneficial_owners`) ```json theme={null} { "uuid": "...", "name": "John Doe", "first_name": "John", "last_name": "Doe", "entity_type": "person", "date_of_birth": null, "country_of_birth": null, "email": null, "company_name": null, "registration_number": null, "nationality": null, "designation": null, "appointment_date": null, "voting_min_shares": null, "voting_max_shares": null, "roles": ["ubo"], "ownership_min_shares": "40", "ownership_max_shares": "40", "is_active": true, "kyc_status": "Pending", "kyc_session_url": "https://verify.didit.me/...", "effective_ownership_percent": 40.0 } ``` `kyc_status` uses a B2C-safe projection: `Approved`, `Declined`, or `Pending` (full session states collapse to `Pending` until the KYC finishes). ## `key_people_checks[]` This is the **aggregate check** over all officers and UBOs for the session. It exposes two buckets so the console can render "extracted from the registry" side-by-side with "submitted by the business", plus a high-level UBO KYC summary. ```json theme={null} { "status": "Approved", "node_id": "feature_kyb_key_people", "registry": { "officers": [ ...registry-derived officers... ], "beneficial_owners": [ ...registry-derived UBOs... ] }, "submitted": { "parties": [ ...user-submitted key-people records... ] }, "ubo_kyc_summary": { "total": 2, "approved": 1, "flagged": 0, "pending": 1 }, "warnings": [] } ``` * **`registry.officers` / `registry.beneficial_owners`** — parties extracted from the registry check. * **`submitted.parties`** — parties the business admin explicitly added during the Key People flow (records with `source = "USER"`). ### `registry.officers[]` / `registry.beneficial_owners[]` The registry facts match `company.officers` / `company.beneficial_owners` above. Key People additionally includes AML status and detailed verification linkage, such as `kyc_session_id` and verification workflow fields. The company lists retain their existing simplified KYC status and verification URL. ### `submitted.parties[]` User-submitted parties carry their KYC or child-KYB linkage: ```json theme={null} { "uuid": "...", "entity_type": "person", "name": "Alice Chen", "first_name": "John", "last_name": "Doe", "email": "alex.sample@example.com", "role": "ubo", "ownership_percent": 35.0, "nationality": "USA", "position": "CEO", "date_of_birth": "1990-01-01", "phone_number": "+34612345678", "source": "USER", "requires_verification": true, "is_skipped": false, "kyc_session_id": "sess-xyz...", "kyc_session_status": "Not Started", "kyc_session_url": "https://verify.didit.me/...", "kyc_session_deleted": false, "custom_fields": { } } ``` Corporate parties (`entity_type: "company"`) additionally carry `company_name`, `registration_number`, and `kyb_sub_session_id` / `kyb_sub_session_status` / `kyb_sub_session_deleted` when nested KYB is enabled for corporate UBOs. `kyc_session_deleted` (and its corporate counterpart `kyb_sub_session_deleted`) is `true` when the party's child session was deleted. A deleted child keeps whatever status it had at deletion time and can never settle, so read this flag rather than the status: the matching `*_session_url` is returned as `null` because the link no longer resolves, and the Key People check drops to `In Review` instead of waiting forever. Deleting a child session never counts as a pass. Exempt the party with [`PATCH /v3/session/{id}/kyb/parties/{party_uuid}/`](/sessions-api/update-data#skip-a-key-people-party) to let the KYB settle. ### `ubo_kyc_summary` Aggregate UBO KYC progress — useful for a single dashboard card: | Field | Meaning | | ---------- | ---------------------------------------------------- | | `total` | Number of active UBOs that have a linked KYC session | | `approved` | UBOs whose KYC session is `APPROVED` | | `flagged` | UBOs whose KYC session is `DECLINED` or `IN_REVIEW` | | `pending` | Everyone else (not yet finished) | Returns `null` when no UBOs have linked KYC sessions. ## `document_verifications[]` Documents grouped by node: ```json theme={null} { "status": "Approved", "node_id": "feature_kyb_documents", "items": [ { "uuid": "...", "document_type": "certificate_of_incorporation", "status": "Approved", "file_url": "https://didit-storage.s3...", "document_metadata": { "file_size": 246810, "content_type": "application/pdf", "creation_date": "2024-05-15", "modified_date": "2024-05-15", "overlay_manipulation": null }, "ocr_data": { "company_name": "Acme Corporation Limited", "registration_number": "12345678", "incorporation_date": "2010-05-14" } } ], "groups": { "legal_presence": { "approved": 1, "pending": 0, "missing": 0 }, "ownership_structure": { "approved": 1, "pending": 0, "missing": 0 } }, "required_groups": ["legal_presence", "ownership_structure"], "warnings": [] } ``` | Field | Description | | ----------------- | ---------------------------------------------------------------------------------------------------------------------- | | `items[]` | Individual document rows — each has its own `status`, `file_url` (signed), `document_metadata`, and OCR extract | | `groups` | Per-group progress counters — matches the [four KYB document groups](/business-verification/documents#document-groups) | | `required_groups` | Groups your workflow marked as required; gate session approval on all being satisfied | ### Corporate document metadata For PDF corporate documents, `items[].document_metadata.overlay_manipulation` can include forensic evidence for suspected overlay-text editing. When present, it includes: | Field | Description | | --------------------- | ----------------------------------------------------------------------------------------------------------------------------- | | `detected` | Whether overlay-text manipulation evidence was detected | | `analyzed` | Whether the PDF could be analyzed | | `signals` | Forensic signals that fired, such as `duplicate_font_subset` or `glyph_fragmentation` | | `manipulated_regions` | PDF page-coordinate rectangles around suspected edited text: `page`, `x`, `y`, `width`, `height`, `page_width`, `page_height` | The field is `null` when no overlay evidence was found, when the document is not a PDF, or when the PDF could not be analyzed. ## `aml_screenings[]` Company-level and (when the workflow wires them) person-level AML screenings. ```json theme={null} { "node_id": "feature_kyb_company_aml", "status": "Approved", "total_hits": 0, "score": 0, "entity_type": "COMPANY", "screened_data": { "company_name": "Acme Corporation Limited", "country_code": "GBR" }, "is_ongoing_monitoring_enabled": true, "next_ongoing_monitoring_bill_date": "2027-04-16", "hits": [], "warnings": [] } ``` When `total_hits > 0`, each hit includes match score, risk score, watchlist sources, and a per-hit `review_status` you can update via the update-aml-hit-status endpoint. See [AML Screening report](/core-technology/aml-screening/report-aml-screening) for the hit structure. ## Shared feature arrays `phone_verifications`, `email_verifications`, `questionnaire_responses`, `ip_analyses` use the same per-item shapes as user (KYC) sessions. They're `null` when the workflow doesn't include them. See the [KYC response](/sessions-api/retrieve-session) for item schemas. ## Warning feature groups Business Verification warnings are grouped by the feature that produced them: * `KYB_REGISTRY` for registry availability, ownership, company activity, and country-restriction issues. * `KYB_DOCUMENTS` for corporate document extraction, cross-check, metadata, manipulation, subtype, age, and attempt-limit issues. * `AML` for company AML screening matches or missing screening data. * `KYB_KEY_PEOPLE` for person-level issues tied to directors, officers, UBOs, or representatives. * `PHONE` for phone-number risk, duplication, blocklist, and verification-code attempt issues. * `EMAIL` for email risk, deliverability, duplication, blocklist, and verification-code attempt issues. * `QUESTIONNAIRE` for custom status rules driven by questionnaire answers. * `LOCATION` for Device & IP Analysis, private-network, IP blocklist, device blocklist, and duplicate device/IP issues. See [Business Verification warnings](/business-verification/warnings) for the full list of warning codes. ## Workflow-driven field filtering Workflows can limit which nested fields appear on each feature item via `response_attributes`. Fields always included regardless: `status`, `warnings`, `node_id`. All other fields are nullified when not in the allow-list — the key stays in the response for schema stability. ## Next steps What each status value means. How `risk_level` is computed. Full AML hit payload reference. How parties flow from registry vs user submission into `registry` / `submitted` buckets. Document groups, OCR, and cross-reference. Full endpoint reference including example responses. # Risk Assessment Source: https://docs.didit.me/business-verification/risk-assessment Composite KYB risk level (LOW/MEDIUM/HIGH) and ownership complexity scoring across registry, AML, key people, documents, and country risk. From $2.00 per check, priced per country and tier. Every KYB decision includes two composite risk signals on the registry check: `risk_level` (`LOW`, `MEDIUM`, `HIGH`) and `ownership_complexity` (`SIMPLE`, `COMPLEX`). They give your compliance team a quick directional read of the business without having to re-score each sub-check on your side. ## Inputs to `risk_level` `risk_level` is a composite Didit computes from the checks that actually ran on the session. The main signals: | Signal | Contribution | | -------------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ | | **Registry status** | An `ACTIVE` / `AUTHORISED` company sits at the low end. `DISSOLVED`, `STRUCK_OFF`, `CLOSED`, `UNAUTHORISED` push toward high. `INACTIVE` or statuses that require manual inspection sit in the middle. | | **Company AML screening** | The company's AML score and hits count. Clean screens sit low; confirmed sanction or adverse-media matches push high. | | **Person AML across key people** | The worst AML result across UBOs, directors, and other key people. Any confirmed sanction / PEP match pushes high. | | **Document completeness** | Whether every required document group is approved, vs missing or failed documents. | | **Country of incorporation** | Country risk tier, based on FATF and OFAC guidance and your dangerous-country policy. | When `risk_level` is `HIGH`, the workflow typically routes the session to `IN_REVIEW` or `DECLINED` depending on your configuration. Exact weighting evolves over time as we tune the model. Treat `risk_level` as a directional signal and combine it with your own policy before making onboarding decisions. ## Inputs to `ownership_complexity` `ownership_complexity` reflects how hard the ownership structure is to unpack. Simple structures have direct natural-person ownership with few UBOs and no opaque intermediaries; complex structures run through multiple corporate layers, cross-border holdings, or trust / foundation / nominee entities. | Value | Typical shape | | --------- | ------------------------------------------------------------------------------------------------ | | `SIMPLE` | Direct natural-person ownership, few UBOs above threshold, no opaque corporate intermediaries | | `COMPLEX` | Multi-layer corporate chains, cross-border ownership, or trust / foundation / nominee structures | `COMPLEX` doesn't automatically imply high risk — but it usually warrants enhanced due diligence. ## Configuration Risk thresholds and related defaults are configurable per workflow in the Business Console: * *Workflows → \[KYB workflow] → Risk → AML thresholds* — set the match-score and risk-score thresholds for approve/review/decline. See [AML risk score](/core-technology/aml-screening/aml-risk-score) and [AML match score](/core-technology/aml-screening/aml-match-score). * *Workflows → \[KYB workflow] → Risk → UBO threshold* — ownership percentage at which someone is classified as a UBO (typically 10%, 25% or 50%). * *Workflows → \[KYB workflow] → Risk → Document policy* — which documents are required vs optional. * *Settings → Blocklist → Countries* — the dangerous-country list used in the country input. ## Illustrative examples The examples below are illustrative of how different signals land — not an exact formula. ### Simple UK Ltd, clean AML * Registry `ACTIVE` * Company AML clean * All key people AML clean * Documents complete * Country `GBR` → `risk_level = LOW`, `ownership_complexity = SIMPLE`. Approved. ### Multi-layer holding with a PEP UBO * Registry `ACTIVE` * Company AML clean * One UBO has an `IN_REVIEW` PEP hit * Documents complete * Country `LUX` → `risk_level = MEDIUM`, `ownership_complexity = COMPLEX` (multi-layer chain). Session routes to `IN_REVIEW`. ### Sanctioned subsidiary detected * Registry `ACTIVE` * Company AML: confirmed sanctions match * One director on a sanctions list → `risk_level = HIGH`. Session auto-declined with reason `aml_confirmed_sanction`. ## Risk color coding in the console * 🟢 `LOW` — green badge. * 🟡 `MEDIUM` — yellow badge. * 🔴 `HIGH` — red badge. `COMPLEX` ownership is shown alongside the risk badge with a small chain icon. ## Using the risk fields on your side ```typescript theme={null} if (decision.status === 'APPROVED' && decision.risk_level === 'HIGH') { // Approved by the engine but still worth a manual reviewer glance await routeToEnhancedDueDiligence(decision); } if (decision.ownership_complexity === 'COMPLEX') { await requireExtraDocumentation(decision); } ``` ## Next steps Status taxonomy. Two-score system used throughout Didit. Where risk fields appear. # KYB Statuses Source: https://docs.didit.me/business-verification/statuses Full reference for KYB session, feature, registry lookup, AML statuses, and decision reason codes. From $2.00 per check, priced per country and tier. Business Verification tracks status at multiple levels: the **session**, individual **features**, the **registry lookup**, and the **AML result**. This page is the reference for every state. ## Session status The overall status of a Business Verification (KYB) session — the single field you'll most often switch on. | Status | Meaning | | --------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | | `NOT_STARTED` | Session created but business has not opened the hosted link. | | `IN_PROGRESS` | Hosted flow is active — registry lookups, document uploads, or AML screening in progress. | | `AWAITING_USER` | Waiting for the end user to take an action (typically submit Key People, or respond to a resubmission request). Transitions automatically once the user completes the pending action. | | `APPROVED` | All required features passed. Business is verified. | | `DECLINED` | A critical check failed (dissolved company, sanctioned entity, blocklisted) or workflow rule rejected. | | `IN_REVIEW` | One or more features require manual analyst review. | | `RESUBMITTED` | Previously declined/resub-requested session has been resubmitted with updated data. | | `ABANDONED` | Business never completed the flow (timeout). | | `EXPIRED` | Session expired before the business completed it. | `AWAITING_USER` is transient — you don't need to manually move sessions out of it. As soon as the end user completes the pending action (for example, submits the Key People list or re-uploads a requested document), Didit re-evaluates the session and transitions it automatically to `IN_REVIEW`, `APPROVED`, or `DECLINED` based on the outcome. ## Feature status Each KYB feature has its own status, which rolls up into the session status. | Status | Meaning | | ----------------- | --------------------------------------------------------------------------------------------------------------------------------------------------------- | | `NOT_FINISHED` | Feature has not yet been started or is mid-run. | | `APPROVED` | Feature passed. | | `DECLINED` | Feature failed (critical). | | `IN_REVIEW` | Feature requires analyst attention. | | `RESUB_REQUESTED` | Business must resubmit for this feature (e.g. re-upload a document). | | `AWAITING_USER` | Feature is waiting for an end-user action. Applies to the Key People feature while the user must submit parties. Automatically transitions on submission. | ### KYB feature names * `kyb_registry` — company registry lookup. * `kyb_company_aml` — company-level AML screening. * `kyb_documents` — document collection and OCR. * `kyb_key_people` — key people: UBOs, shareholders, directors, representatives and other officers. ## Registry status (from the provider) The official status of the company as obtained from authoritative registry sources. Reflects the legal or regulatory standing of the entity as reported by the jurisdiction-specific registry, so exact values vary by source. Surfaced inside the KYB decision under `company.registry_status`. | Status | Meaning | | -------------------------- | ---------------------------------------------------- | | `ACTIVE` | Company is active and in good standing. | | `DISSOLVED` | Company has been dissolved. | | `DEREGISTERED` | Company has been deregistered. | | `STRUCK_OFF` | Company has been struck from the registry. | | `CLOSED` | Company has been closed. | | `INACTIVE` | Company is inactive (non-trading). | | `AUTHORISED` | Authorised (typically for regulated entities). | | `APPOINTED_REPRESENTATIVE` | Appointed representative of another authorised firm. | | `UNAUTHORISED` | Previously authorised, now unauthorised. | | `NO_LONGER_AUTHORISED` | Authorisation revoked. | | `SEE_FULL_DETAILS` | Status requires manual inspection. | Because `registry_status` reflects raw registry values, use `verification_status` below when you need a consistent, cross-jurisdiction indicator to drive product logic. ## Company verification status A standardized, business-facing status per company result. Normalizes the varying registry and company statuses across different countries and sources into a single consistent indicator that can be interpreted directly within your product. Surfaced inside the KYB decision under `company.verification_status`. | Status | Meaning | | ---------- | ------------------------------------------------------------------ | | `verified` | The company appears active and valid. | | `failed` | The company appears inactive, dissolved, or has issues identified. | | `unknown` | There is insufficient information or the status is ambiguous. | ## Company fetch status Indicates the data retrieval progress for a specific company record from external or official registries. Use it to determine how complete the fetched information is for a given company. Surfaced inside the KYB decision under `company.fetch_status`. | Status | Meaning | | ---------- | ------------------------------------------------------------------------------------- | | `pending` | Only partial or basic company information has been retrieved at this stage. | | `resolved` | Full and complete company data has been successfully retrieved from official sources. | ## AML verification status Returned per screening (company or person). | Status | Meaning | | -------------- | ---------------------------------------------------- | | `APPROVED` | No hits above threshold. | | `DECLINED` | High-severity hit (confirmed sanction or PEP match). | | `IN_REVIEW` | Hit found that requires analyst review. | | `NOT_FINISHED` | Screening has not completed. | ## Decision reason codes When a session is `DECLINED`, the decision includes a machine-readable `decision_reason_code`. Common codes: | Code | Meaning | | ---------------------------- | -------------------------------------------------------------- | | `blocked_country` | Country of incorporation is in the dangerous countries list. | | `blocked_business` | The `vendor_data` matches a Business blocklist entry. | | `registry_company_not_found` | Company could not be located in any supported registry. | | `registry_company_dissolved` | Registry reports company is dissolved. | | `registry_mismatch` | Registry data contradicts the customer-provided data. | | `aml_confirmed_sanction` | Confirmed sanctions match on the company or a key person. | | `aml_confirmed_pep` | Confirmed PEP match on a key person. | | `documents_failed_ocr` | Uploaded documents could not be OCR'd or fail cross-reference. | | `documents_incomplete` | Required documents missing. | | `key_people_incomplete` | UBOs or officers below threshold could not be identified. | | `analyst_rejected` | An analyst manually declined after review. | | `timeout_abandoned` | Business did not complete the flow within the SLA. | Additional workflow-specific reason codes may appear — see your workflow configuration for the full list. ## Ownership and complexity signals Returned in the decision alongside status, for informational use: | Field | Description | | ---------------------- | ------------------------------------------------------------------------------- | | `risk_level` | `LOW`, `MEDIUM`, `HIGH` — composite of registry, AML, and ownership complexity. | | `ownership_complexity` | `SIMPLE`, `COMPLEX` — based on number of ownership layers and entity types. | See [risk assessment](/business-verification/risk-assessment) for how these fields are computed. ## Next steps Where each status appears in the payload. How statuses combine into a risk level. Events that fire on status changes. # Supported Countries Source: https://docs.didit.me/business-verification/supported-countries KYB registry coverage across 220+ countries, with the Lite, Shareholders and UBO data tiers available per jurisdiction. From $2.00 per check, priced per country and tier. Didit's Business Verification (KYB) provides broad global coverage for company registry lookups, sold in three data tiers — see [KYB registry pricing](/getting-started/kyb-registry-pricing) for what each tier returns and what it costs. Tier availability varies by country — the table below shows which tiers are available for each jurisdiction. Customize which countries your workflows collect, and the tier per country, via the console [workflows](/console/workflows) — align coverage to your compliance footprint without paying for a tier you don't need. ### Tier columns | Column | What it means | | ---------------- | ----------------------------------------------------------------------------------------------------- | | **Lite** | Company profile, identifiers, status, registered address, activity, and officers | | **Shareholders** | Lite plus the direct shareholders (natural persons and corporate entities) with their ownership bands | | **UBOs** | Shareholders plus the ultimate beneficial owners resolved through the ownership chain | Cells marked ✅ indicate the tier is available for that jurisdiction; — means the registry holds no data at that tier there. A Shareholders or UBO request in a country whose registry holds no ownership record is delivered and billed at the highest tier the country's registries can serve — usually Lite. A country with no ✅ at any tier is not offered for registry checks: the applicant enters the company manually, billed at the flat manual-entry price. *** ## Supported countries and subdivisions The table below shows all supported countries and subdivisions. The **Code** column contains the [ISO 3166-1 alpha-2](https://en.wikipedia.org/wiki/ISO_3166-1_alpha-2) country code used across Didit KYB APIs (e.g. in `country_code` on the registry check, session creation, and business entity fields). US states use the extended `US_` format (e.g. `US_CA`, `US_NY`, `US_DE`) to select the correct Secretary of State registry. *** ## Manual entry A country with no tier available above, or a company the registry cannot find, is not blocked — the applicant enters the company by hand and the step continues with `is_from_registry: false`, billed at the flat manual-entry price (see [KYB registry pricing](/getting-started/kyb-registry-pricing)). Some jurisdictions route these sessions to `IN_REVIEW` automatically with reason `registry_manual_required`, depending on your workflow configuration. ## US state coverage US registries are organized per state. To run a KYB check on a US company, pass the `US_` code (e.g. `US_DE` for Delaware, `US_CA` for California, `US_NY` for New York) — every US state and DC is supported. Using just `US` falls back to a federal-only search (company name + status). Per-state coverage of officers, shareholders, and UBOs varies — Delaware, California, Texas, and New York expose the richest officer and filing data, while smaller states often return only company name, status, and registered agent. ## Dangerous / sanctioned countries By default, companies incorporated in any country on your application's [dangerous countries](/entities/businesses/blocklist#dangerous-countries) list are auto-declined at session creation regardless of whether the registry is supported. Default list follows FATF and OFAC guidance: * `AF` Afghanistan * `IR` Iran * `KP` Korea, Dem. Republic of * `SY` Syria * `RU` Russian Federation — sectoral sanctions * `MM` Burma (Myanmar) Configure the list from *Settings → Blocklist → Countries*. ## Ongoing monitoring Company AML screening can be configured for **ongoing monitoring** — periodic rescans against sanctions and adverse media lists. See [continuous AML monitoring](/core-technology/aml-screening/continuous-monitoring-aml-screening). ## Continuous registry monitoring Registry monitoring is **coming soon**. No country in the staging retail catalog checked on September 7, 2026 has monitoring enabled. The configured rate is USD 2.00 per company per year; a price does not mean the feature is available. The behavior below describes the planned service after rollout. Companies verified at the **Shareholders** or **UBO** tier can be kept under continuous registry monitoring for **\$2.00 per company per year**: the registry pushes changes of status, officers, ownership and address, the session goes back to review and a `kyb_registry_change` webhook fires. It is only available where the country allows it: the countries below. See [monitoring shareholders and UBOs](/business-verification/ownership#monitoring-shareholders-and-ubos) and the [per-country prices](/getting-started/kyb-registry-pricing). ## Registry data sources Didit routes each query to the appropriate official government registry or an authoritative aggregator based on the jurisdiction and subdivision you specify. Data is refreshed on every session — results reflect the latest registry state at query time. Need a country or subdivision that isn't listed here? [Contact us](mailto:support@didit.me) — registry coverage expands regularly based on customer demand. ## Next steps How KYB uses registry data. What registry fields get extracted. # Business Verification Warnings Source: https://docs.didit.me/business-verification/warnings Business Verification warning codes grouped by feature: KYB registry, KYB documents, KYB key people, AML, phone, email, questionnaire, and Device & IP Analysis. Business Verification surfaces warnings on the feature item that produced them. Each warning carries the standard structured shape used across the platform — `feature`, `risk`, `log_type`, `short_description`, `long_description`, optional `additional_data`, and `node_id` — so you can route review work to the right operational team. ## Overview KYB sessions emit warnings under three core feature tags that map to dedicated feature arrays in the V3 decision response: | Feature tag | Decision response key | What it covers | | ---------------- | ------------------------------------- | ---------------------------------------------------------------------------------------------------------------------------------------------------------------- | | `KYB_REGISTRY` | `registry_checks[].warnings[]` | Official company-registry lookups. Active status, country restrictions, derivable ownership, missing officer/UBO records. | | `KYB_DOCUMENTS` | `document_verifications[].warnings[]` | Incorporation, ownership, address, and shareholder documents the user uploads. Cross-document consistency, OCR, metadata, manipulation, age, and subtype rules. | | `KYB_KEY_PEOPLE` | `key_people_checks[].warnings[]` | Person-level signals on directors, officers, UBOs, or user-submitted parties — including PEP/sanctions findings that propagate from AML and prior-decline reuse. | The same KYB workflow can also include the shared features below — they emit warnings on their own arrays: | Feature tag | Decision response key | | --------------- | ------------------------------------------------------------ | | `AML` | `aml_screenings[].warnings[]` | | `PHONE` | `phone_verifications[].warnings[]` | | `EMAIL` | `email_verifications[].warnings[]` | | `QUESTIONNAIRE` | `questionnaire_responses` (warnings live on the session log) | | `LOCATION` | `ip_analyses[].warnings[]` | ## KYB Registry warnings Registry warnings use `feature: "KYB_REGISTRY"` and appear on `registry_checks[].warnings[]`. | Tag | Description | | ---------------------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ | | `KYB_COUNTRY_RESTRICTED` | The company's country is outside the allowed countries configured for the workflow. | | `KYB_OFFICERS_DATA_NOT_FOUND` | Officer data is not available from the registry. | | `KYB_OWNERSHIP_DATA_NOT_FOUND` | Ownership data is not available from the registry. | | `KYB_BENEFICIAL_OWNERSHIP_NOT_DERIVABLE` | Ultimate beneficial ownership could not be established from the registry data. | | `KYB_COMPANY_NOT_ACTIVE` | The company is not active according to the registry. | | `KYB_COMPANY_NOT_FROM_REGISTRY` | The company was entered manually and could not be verified against a corporate registry. | | `KYB_COMPANY_VAT_INVALID` | The company's VAT number was checked against the EU VIES service and is not valid. The configured `kyb_vat_invalid_action` is applied (default: In Review). | | `KYB_COMPANY_VAT_COULD_NOT_VALIDATE` | The VAT number could not be validated because the EU VIES service (or the member state) was temporarily unavailable. The configured `kyb_vat_unverified_action` is applied (default: no effect). | | `KYB_COMPANY_VAT_NAME_MISMATCH` | The trader name registered with VIES for this VAT number differs from the submitted company name. Informational — includes `vies_name` and `submitted_name` in `additional_data`. | VAT warnings only apply to companies in the EU VAT area (EU-27 plus Northern Ireland) — see [VAT validation](/business-verification/company-data#vat-validation-vies). ## KYB Document warnings Document warnings use `feature: "KYB_DOCUMENTS"` and appear on `document_verifications[].warnings[]`. | Tag | Description | | ------------------------------------------ | ------------------------------------------------------------------------------------------------------- | | `KYB_DOCUMENT_MISSING_REQUIRED_FIELD` | A required company field — such as company name or registration number — was not found in the document. | | `KYB_DOCUMENT_NAME_MISMATCH` | The company name in the document does not match the registry. | | `KYB_DOCUMENT_REG_NUMBER_MISMATCH` | The registration number in the document does not match the registry. | | `KYB_DOCUMENT_INCORPORATION_DATE_MISMATCH` | The incorporation date in the document does not match the registry. | | `KYB_DOCUMENT_ADDRESS_MISMATCH` | The registered address in the document does not match the registry. | | `KYB_CROSS_DOCUMENT_MISMATCH` | Company data differs across uploaded corporate documents. | | `KYB_DOCUMENT_METADATA_MISMATCH` | The document signature, metadata, or file structure indicates a possible issue. | | `KYB_ASSOCIATED_PARTY_MISMATCH` | Directors or shareholders in the document do not match the registry. | | `KYB_DOCUMENT_GRAPHIC_EDITOR` | The document appears to have been processed by graphic editing software. | | `KYB_DOCUMENT_SUSPECTED_MANIPULATION` | The system detected signs of possible corporate-document manipulation. | | `KYB_ADDITIONAL_DATA_NOT_FOUND` | A document field could not be verified because the corresponding registry data is unavailable. | | `KYB_DOCUMENT_EXPIRED` | The corporate document exceeds the configured maximum age. | | `KYB_DOCUMENT_UNSUPPORTED_SUBTYPE` | The uploaded document subtype is disabled for the workflow. | | `KYB_DOCUMENT_MAX_ATTEMPTS_EXCEEDED` | The maximum number of corporate-document upload attempts was exceeded. | For PDF overlay-text manipulation, `KYB_DOCUMENT_SUSPECTED_MANIPULATION` can include `additional_data.manipulated_regions`. These are page-coordinate rectangles that identify the suspected edited areas and match the rectangles returned in `document_verifications[].items[].document_metadata.overlay_manipulation.manipulated_regions`. ## KYB Key People warnings Key People warnings use `feature: "KYB_KEY_PEOPLE"` and appear on `key_people_checks[].warnings[]`. They surface person-level issues on directors, officers, UBOs, and user-submitted parties. | Tag | Description | | ------------------------------------ | ----------------------------------------------------------------------------------------------------------------------- | | `KYB_PREVIOUSLY_DECLINED_INDIVIDUAL` | A person associated with the company was previously declined in another business verification for the same application. | **PEP / sanctions hits on key people** are reported as standard AML hits on the matching `aml_screenings[]` item, not as a KYB-key-people warning. The Key People check propagates the resulting `Declined` or `In Review` status onto each affected party so the overall key-people verdict reflects the AML outcome. ## Shared feature warnings The features below can run inside a KYB workflow. They use the same warning catalog as User Verification — full reference on each feature's own warnings page. ### AML `feature: "AML"` on `aml_screenings[].warnings[]`. | Tag | Description | | --------------------------------- | ----------------------------------------------------------------------------------------------------- | | `POSSIBLE_MATCH_FOUND` | The AML screening found a possible match requiring review. | | `COULD_NOT_PERFORM_AML_SCREENING` | Didit could not perform the AML screening because required screening data was missing or unavailable. | ### Phone `feature: "PHONE"` on `phone_verifications[].warnings[]`. | Tag | Description | | ------------------------------------- | -------------------------------------------------------------- | | `DISPOSABLE_NUMBER_DETECTED` | The phone number is disposable. | | `VERIFICATION_CODE_ATTEMPTS_EXCEEDED` | The maximum number of verification-code attempts was exceeded. | | `VOIP_NUMBER_DETECTED` | The phone number is a VoIP number. | | `DUPLICATED_PHONE_NUMBER` | The phone number was used in another verification process. | | `HIGH_RISK_PHONE_NUMBER` | The phone number is high risk. | | `PHONE_NUMBER_IN_BLOCKLIST` | The phone number matches an entry in your blocklist. | ### Email `feature: "EMAIL"` on `email_verifications[].warnings[]`. | Tag | Description | | ------------------------------ | -------------------------------------------------------------------- | | `BREACHED_EMAIL_DETECTED` | The email address appears in known data breaches. | | `DISPOSABLE_EMAIL_DETECTED` | The email address is disposable. | | `UNDELIVERABLE_EMAIL_DETECTED` | The email address is undeliverable. | | `DUPLICATED_EMAIL` | The email address was used in another verification process. | | `EMAIL_IN_BLOCKLIST` | The email address matches an entry in your blocklist. | | `EMAIL_CODE_ATTEMPTS_EXCEEDED` | The maximum number of email verification-code attempts was exceeded. | ### Questionnaire `feature: "QUESTIONNAIRE"`. | Tag | Description | | ------------------------------ | --------------------------------------------------------------------------------------- | | `CUSTOM_STATUS_RULE_TRIGGERED` | A workflow status rule evaluated a questionnaire answer and changed the feature status. | ### Device & IP Analysis `feature: "LOCATION"` on `ip_analyses[].warnings[]`. | Tag | Description | | ------------------------------------------------------ | ------------------------------------------------------------------------------------------ | | `COUNTRY_FROM_DOCUMENT_DOES_NOT_MATCH_COUNTRY_FROM_IP` | The document country does not match the IP country. | | `PRIVATE_NETWORK_DETECTED` | A private network, VPN, proxy, or Tor signal was detected. | | `EXPECTED_IP_ADDRESS_MISMATCH` | The IP address does not match the expected IP address provided for the session. | | `IP_ADDRESS_IN_BLOCKLIST` | The IP address matches an entry in your blocklist. | | `DEVICE_FINGERPRINT_IN_BLOCKLIST` | The device fingerprint matches an entry in your blocklist. | | `DUPLICATED_IP_ADDRESS` | The same IP address was used in another verification with different `vendor_data`. | | `DUPLICATED_DEVICE_FINGERPRINT` | The same device fingerprint was used in another verification with different `vendor_data`. | ## Examples ### Registry — company not active ```json theme={null} { "registry_checks": [ { "node_id": "feature_kyb_registry", "status": "Declined", "warnings": [ { "feature": "KYB_REGISTRY", "risk": "KYB_COMPANY_NOT_ACTIVE", "log_type": "error", "short_description": "Company is not active", "long_description": "The company is not active according to the registry.", "additional_data": null, "node_id": "feature_kyb_registry" } ] } ] } ``` ### Documents — suspected overlay manipulation ```json theme={null} { "document_verifications": [ { "node_id": "feature_kyb_documents", "status": "In Review", "warnings": [ { "feature": "KYB_DOCUMENTS", "risk": "KYB_DOCUMENT_SUSPECTED_MANIPULATION", "log_type": "warning", "short_description": "Possible document manipulation", "long_description": "The system detected signs of possible corporate-document manipulation.", "additional_data": { "manipulated_regions": [ { "page": 1, "x": 120, "y": 240, "width": 180, "height": 22, "page_width": 612, "page_height": 792 } ] }, "node_id": "feature_kyb_documents" } ] } ] } ``` ### Key people — previously declined individual ```json theme={null} { "key_people_checks": [ { "node_id": "feature_kyb_key_people", "status": "In Review", "warnings": [ { "feature": "KYB_KEY_PEOPLE", "risk": "KYB_PREVIOUSLY_DECLINED_INDIVIDUAL", "log_type": "warning", "short_description": "Previously declined individual", "long_description": "A person associated with the company was previously declined in another business verification for the same application.", "additional_data": null, "node_id": "feature_kyb_key_people" } ] } ] } ``` ## Related See where warnings appear in each KYB feature array. Understand how warning severity maps to verification status. Review document groups, OCR, and cross-check behavior. Officer, UBO, and submitted-party verification flow. Hit-level structure for company and person AML screenings. Canonical shapes for warnings and feature arrays. # KYB Webhooks Source: https://docs.didit.me/business-verification/webhooks Webhook events for KYB sessions and Business entities — triggers, payload schemas, and HMAC signature verification. From $2.00 per check, priced per country and tier, no contracts. Business Verification and Business entities emit webhook events on every meaningful state change. Subscribe to the events you care about via the [webhook destinations API](/management-api/webhook/list-destinations) or the Business Console. ## Event catalog Webhook events are shared between User and Business sessions — the `session_kind` field on the payload tells you which kind the event refers to. Entity-level events are separate from session-level events. ### Session-level events | Event | When it fires | | ---------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------ | | `status.updated` | A session's status changed. For Business Verification (KYB) sessions the payload carries `session_kind: "business"`. | | `data.updated` | A session's data was updated (registry refresh, key-people submission, document upload, AML rescan). Payload includes `session_kind: "business"` for KYB sessions. | ### Business entity events | Event | When it fires | | ------------------------- | ---------------------------------------------------------------------------------------------------------------- | | `business.status.updated` | The linked [Business entity](/entities/businesses/overview)'s status changed (`ACTIVE` / `FLAGGED` / `BLOCKED`). | | `business.data.updated` | The Business entity's profile fields or aggregate counters changed. | Subscribe to any combination on your webhook destination. See [entity webhooks](/entities/webhooks) for the full Business / User entity event reference. ## Envelope Every webhook uses the same top-level envelope. The `session_kind` field inside `data` discriminates between User Verification (KYC) and Business Verification (KYB) for session-level events. ```json theme={null} { "event": "status.updated", "event_id": "evt_01H8X...", "application_id": "app_abc123", "timestamp": "2026-04-18T12:30:00Z", "data": { ... } } ``` ## Payload shapes ### `status.updated` — Business Verification (KYB) session Fires when a KYB session's status transitions. ```json theme={null} { "event": "status.updated", "data": { "session_id": "bs_01H...", "session_kind": "business", "previous_status": "IN_PROGRESS", "status": "APPROVED", "vendor_data": "biz-acme-001", "workflow_id": "wf_kyb_standard", "features": ["KYB_REGISTRY", "KYB_COMPANY_AML", "KYB_DOCUMENTS", "KYB_KEY_PEOPLE"], "decision": { ...abbreviated KYB decision payload... }, "changed_at": "2026-04-18T12:30:00Z" } } ``` The `decision` block contains the same shape as [`GET /v3/session/{id}/decision/`](/sessions-api/retrieve-session) — `registry_checks[]`, `key_people_checks[]`, `document_verifications[]`, `aml_screenings[]`, etc. ### `data.updated` — Business Verification (KYB) session Fires when session data (registry, key people, documents, AML) changed without a status transition. ```json theme={null} { "event": "data.updated", "data": { "session_id": "bs_01H...", "session_kind": "business", "vendor_data": "biz-acme-001", "changed_fields": ["registry_checks", "key_people_checks"], "updated_at": "2026-04-18T14:00:00Z" } } ``` Use `changed_fields` to efficiently decide what to re-fetch. ### `business.status.updated` Fires when the [Business entity](/entities/businesses/overview) moves between `ACTIVE`, `FLAGGED`, or `BLOCKED`. ```json theme={null} { "event": "business.status.updated", "data": { "vendor_data": "biz-acme-001", "uuid": "f7a9c1b2-4e6d-4f8a-9c5d-2a1b3c4d5e6f", "status": "FLAGGED", "previous_status": "ACTIVE", "reason": "manual", "actor": "compliance@yourcorp.com" } } ``` ### `business.data.updated` Fires when the Business entity's profile fields or aggregate counters change. ```json theme={null} { "event": "business.data.updated", "data": { "vendor_data": "biz-acme-001", "uuid": "...", "legal_name": "Acme Corporation Limited", "registration_number": "12345678", "country_code": "GBR", "session_count": 2, "approved_count": 1, "declined_count": 0, "in_review_count": 1, "changed_fields": ["session_count", "approved_count", "features"] } } ``` ## Signature verification All webhooks are signed HMAC-SHA256 with your destination's shared secret, sent in the `X-Didit-Signature` header. Verify the raw request body before acting. Example (Node.js): ```typescript theme={null} import { createHmac, timingSafeEqual } from 'crypto'; function verifyWebhook(rawBody: string, signature: string, secret: string): boolean { const expected = createHmac('sha256', secret).update(rawBody).digest('hex'); const provided = Buffer.from(signature); const computed = Buffer.from(expected); return provided.length === computed.length && timingSafeEqual(provided, computed); } ``` Full details in the [webhooks reference](/integration/webhooks). ## Retry policy * Non-2xx responses trigger retries with exponential backoff. * Up to 5 retries over \~24 hours. * Each retry gets a new `X-Didit-Delivery` header but the same `event_id` — de-duplicate on your side. * Repeated failures flip the destination to `disabled`. ## Subscribing Subscribe to the events you care about on a [webhook destination](/management-api/webhook/create-destination): ```bash theme={null} curl -X POST https://verification.didit.me/v3/webhook/destinations/ \ -H "x-api-key: YOUR_API_KEY" \ -H "Content-Type: application/json" \ -d '{ "label": "KYB events", "url": "https://yourapp.com/webhooks/didit-kyb", "subscribed_events": [ "status.updated", "data.updated", "business.status.updated", "business.data.updated", "activity.created" ] }' ``` Filter for business sessions on your side by checking `data.session_kind === "business"` inside `status.updated` and `data.updated` events. ## Next steps Destinations, signing, retries, common patterns. Session and feature status reference. Decoding the KYB decision payload. # April 2026 Source: https://docs.didit.me/changelog/april-2026 April 2026 release: KYB business verification revamp, transaction monitoring upgrades, streaming exports, new documents, and native SDK updates. ### KYB Business Verification — Major Revamp Business verification received its biggest update yet. The end-to-end flow — from creating a session to reviewing the final report — was rebuilt around the same patterns you already know from KYC. * **New Business List View** — Filters, column visibility, tags, bulk actions, and create-session shortcuts make managing business onboarding far easier * **Redesigned Business Detail Page** — Scrollable feature tabs (registry, key people, documents, AML, questionnaires), PDF download, file preview, resubmit, and delete — matching the session detail experience * **Key People Graph** — Split view between registry-provided and submitted parties, clickable detail modal, and a workflow-style hierarchy graph (Cmd/Ctrl + scroll to zoom) * **Expanded Registry Check** — More fields, richer inline editing, country flags with localized names, and translated labels for addresses, financials, and industries * **AML for KYB** — Configure AML screening for businesses and their key people with the same controls as KYC * **Required Document Validation** — Workflows can now require at least one verified business document (incorporation, POA, etc.) before approval * **Tags, Cases, and Decision Endpoints** — Tag businesses, attach cases, and apply manual decisions through the same APIs used for individuals KYB key people hierarchy graph in the Didit Business Console ### Customer-Facing KYB Flow The end-user side of KYB also saw heavy work for a smoother onboarding experience. * **Smart Prefill** — Phone numbers and key people are prefilled when the data is already known, so applicants only confirm * **POA Improvements** — Better proof-of-address screen, document subtype detection, and a new action when the address can't be parsed * **KYB Document Compression** — Uploaded business documents are now compressed automatically for faster submission and smaller payloads * **Region Picker Polish** — Redesigned country and state pickers shared across every step for a more consistent feel Customer-facing KYB flow — company search step ### Transaction Monitoring (KYT) Transaction monitoring grew from a beta feature into a full surface area inside the Console. * **Transaction PDF Reports** — Download a complete PDF for any transaction, matching the format already available for verification sessions * **Lists & Blocklists Expanded** — System lists now cover IPs, devices, and duplicated identifiers, with translations and richer match details * **Rules Summary** — Each transaction shows only the rules that actually matched, with a count summary at the top * **Cases on User Details** — User profiles now surface their associated cases, transactions, and screening history in one place * **Improved Screening Performance** — AML screening responses are cached, transaction screening is faster, and rule responses are more compact * **Subject Country Fix** — Cross-border transactions resolve the correct subject country * **Webhooks for Transactions** — Get notified when transaction state changes via the same webhook system as sessions * **Payment Methods** — Payment-method data is now captured and surfaced on the transaction record Transaction monitoring list view in the Didit Business Console ### Database Validation * **New Service Format** — Database validation services moved to a richer format that returns more structured data for downstream use * **Outcome Codes** — Standardized outcome codes make it easier to map vendor responses across countries ### Streaming CSV Exports Large exports no longer time out. Sessions, transactions, analytics, and usage exports stream results as they're generated. * **Sessions & Businesses Export** — Streamed CSV with no row cap and far lower memory usage * **Analytics Export** — Download analytics data as a CSV directly from the dashboard * **Usage Export** — Per-feature usage breakdown is now exportable * **Faster Generation** — Exports complete several times faster on large organizations Exporting sessions to CSV from the Didit Business Console ### Multi-Account Abuse Prevention New protection against organization farming — when a single actor creates multiple sub-accounts to bypass limits. * **Multi-Account Detection** — Suspicious patterns of organization creation are now flagged automatically * **New Roles & Permissions** — Additional granular permissions, plus updates to SAML for enterprise customers ### Workflow & API Improvements * **More Flexible Workflow API** — Create and patch workflows with a wider range of configurations, including KYB settings and node deduplication * **Workflow Editor Polish** — Template fixes, blur/scroll improvements in the node editor, redesigned modals, and clearer node-based UI * **Custom Verification Email** — Send the verification link from a dedicated email channel * **Update-Data Endpoints for API Clients** — The endpoints used to update session data are now first-class, available to all API clients * **Workflow Templates** — More templates and better preview screens Didit workflow and API improvements ### Console Performance & UX * **Faster Console** — Reduced initial load time and smoother navigation across the dashboard * **Phone Lifecycle** — Cleaner state transitions for phone-verification features * **User Details Pages** — All tabs (sessions, businesses, transactions, cases) now visible on a single user-detail surface * **Permissions Fixes** — Several Console buttons that were incorrectly disabled (e.g., the "+" create button) now reflect the user's real permissions ### New Document & Country Support * **Kyrgyzstan** — Added support for the national ID * **India** — PAN ID card now correctly classified, separate from passports * **Mexico** — New ID document added; Switzerland and Czech Republic recognition improved * **Algeria** — CSCA chip validation now works correctly * **Income Tax Cards** — New document type for tax-residency verification across multiple regions ### Kazakh Language The verification flow, Console, and SDKs now support Kazakh (kk), bringing total language coverage to 53. ### Native SDKs A wave of releases across all native SDKs this month, focused on stability and reliability. * **Android SDK 3.4.4 – 3.5.3** — Improved document and face overflow detection, better photo quality, refined face-intro styling, fixed close buttons and verification screen styling, and updated languages including Kazakh * **iOS SDK 3.2.10 – 3.3.3** — Multiple stability releases with active liveness improvements, language updates, and miscellaneous fixes * **React Native SDK 3.2.8 – 3.2.9** — Resolved Swift 6 main-actor isolation error on Xcode 26.0.x, surfaced the new `RetryBlocked` error variant, added an Expo example app, and improved the CI pod-install fallback * **Flutter SDK 3.4.4 – 3.4.5** — Fixed Swift 6 exhaustive switch, updated native iOS/Android SDKs underneath, and surfaced `RetryBlocked` from the native Android layer ### MCP Server The Didit MCP server (used by AI agents) was upgraded. * **Lists API** — Legacy blocklist tools were replaced with the unified Lists API, giving agents the same blocklist/allowlist capabilities the Console exposes * **Version 3.0.3** — Latest release published ### Improvements * IP enrichment now handles private IP addresses gracefully * KYB sub-sessions (KYC for UBOs, officers, etc.) correctly inherit the whitelabel branding of their parent * WebSocket responses include the user's locale for client-side display * Active liveness uses the latest verification SDK with faster capture validation on iOS * Camera permission handling distinguishes between permission timeouts and scan timeouts for clearer error messages * Arabic transliteration improved * Country detection from IP fixed for several edge-case ranges * Fraud reports include richer detail and a clearer summary # April and May 2025 Source: https://docs.didit.me/changelog/april-may-2025 Didit V2 launch with modular architecture, age estimation, biometric authentication, proof of address, prepaid credits, and open APIs. ### Didit V2 Is Here We've rebuilt Didit from the ground up. This is not just an update — it's a reimagining of how identity verification should work. **Modular Architecture** — Choose only the tools you need. Use our web widget or go deep with our open APIs. **New Features:** * **Age Estimation** — Facial analysis to verify user age, with optional document check * **Biometric Authentication** — Use biometrics to unlock sensitive flows like payments or restricted access * **Proof of Address** — Accept bills, bank statements, or cross-reference data to verify residency * **Face Search 1:N** — Match a user's face against your database to detect duplicates, enforce blocklists, or manage biometric access * **Phone Verification** — OTP-based phone number checks built-in **More Control** — Fully customize your verification flow based on your risk and product needs. **Prepaid Credit Model** — Buy only what you use. Save more on premium features like AML, Biometrics, and Age Estimation. **Open & Modular APIs** — Core features exposed via API so you can integrate directly without the hosted verification flow. # August 2025 Source: https://docs.didit.me/changelog/august-2025 Database validation API launch, phone verification, proof of address by country, and RTL language support across Didit's identity verification platform. * **Database Validation** — New API for verifying identity against government databases. Launched coverage for Brazil and Dominican Republic * **Phone Verification** — New phone verification API integrated into biometric authentication flows * **Proof of Address by Country** — POA documents can now be configured per country for flexible integrations * **Unparsed Address Warning** — Notifications when document addresses cannot be parsed or geolocated * **Enhanced Document Handling** — Additional personal number fields, improved non-standard MRZ handling (Peru, Bolivia, Romania, Iraq, Kazakhstan, Kuwait) * **Language & RTL Support** — Full right-to-left interface improvements for Arabic, Hebrew, and Persian * **Improved iOS Capture Quality** — Optimized image and video quality on iOS while keeping file sizes lightweight * **Shorter Session URLs** — Smaller QR codes and more readable URLs * **Automatic Language Routing** — Language auto-detection when scanning QR codes and during redirections * **Bug Fixes** — Fixed face match edge cases, improved video compression, fixed Samsung Internet compatibility issues # August 2026 Source: https://docs.didit.me/changelog/august-2026 Biometric-template retention with a breaking session-deletion change, new fraud signals, ISO/IEC 27566-1 age assurance, and standalone risk APIs. ### Stronger fraud detection Fraudsters increasingly submit documents and selfies that never came from a real capture. Five new signals catch those submissions before they reach a reviewer. * **Catch recycled document images** — every upload is scored against a corpus of ID document images already circulating publicly, and a match raises its own warning * **Liveness video forensics** — frame count, duplicate-frame ratio, and effective frame rate are analyzed server side, so replayed or synthetic video is flagged rather than trusted * **Covered documents are detected** — a partially obscured document is caught at pixel level and returns `DOCUMENT_OCCLUSION_DETECTED`, translated into every supported language * **Live capture confirmed** — Face Match confirms the person in front of the camera, distinguishing a live capture from the portrait printed on the document * **Capture quality gate** — every upload is scored for quality before extraction runs, so a poor capture is caught while the user is still in the flow Didit card titled Five new fraud signals ### Age assurance built to ISO/IEC 27566-1 Age-assurance workflows can now return the age decision and nothing else, in line with the international age-assurance standard. * **Returned data is locked** — a workflow that declares the age-assurance standard cannot return identity attributes alongside the age decision, and only an age-capable workflow may declare it * **Branch on a borderline age** — the Age Estimation borderline band is visible to the workflow graph, so an uncertain result can route to a document check instead of a flat pass or fail * **Ready-made templates** — start from an age-assurance template in the workflow builder with returned data already restricted Didit card titled Age assurance, ISO/IEC 27566-1 ### New standalone APIs Four capabilities that previously required a full verification session are now callable on their own, each priced per call on the [pricing page](https://didit.me/pricing). * **Document AI** — `POST /v3/document-ai/` extracts structured data from any uploaded document, not just identity documents. See [Document AI](/standalone-apis/document-ai) * **Contact and network risk** — `POST /v3/email/risk/`, `POST /v3/phone/risk/`, and `POST /v3/ip/risk/` return risk signals for an email address, phone number, or IP address. See [Email risk](/standalone-apis/email-risk), [Phone risk](/standalone-apis/phone-risk), and [IP risk](/standalone-apis/ip-risk) * **Run them as a single check** — each is also available from the single-check dialog in the **Business Console**, without building a workflow Didit card titled Document AI and risk APIs ### Didit Copilot The in-console assistant became a floating copilot that cites its sources and can build a working workflow from a description. * **Available on every page** — a resizable floating panel replaces the docked one, with starting prompts for the page you are on and a fullscreen layout on mobile * **Answers cite their sources** — inline citations open the underlying documentation without leaving the panel * **Build a workflow by describing it** — the copilot creates the draft, adds and configures steps, adds branches, sets final-status rules, and validates before publishing * **Configure Database Validation by conversation** — the copilot creates a configured **Database Validation** step for any supported country * **Build a questionnaire from a spreadsheet** — attach a CSV or Excel file and the copilot turns it into a questionnaire, including very long answer lists * **Works in your language** — the console language travels with every turn, voice and typed input are both supported, and you can download the transcript