> ## Documentation Index
> Fetch the complete documentation index at: https://docs.prov.ae/llms.txt
> Use this file to discover all available pages before exploring further.

# Screen numbers for DNCR, other agents, and our staff

> Runs the DNCR check, the broker-register check and the Provident-staff check on the same numbers, up to 20 (the DNCR limit). Enabled separately: access to this endpoint does not include the three separate ones, and access to them does not include this one. `ourAgent` says whether a number belongs to a Provident employee (current or former, work or personal) and never who. A number that is not a UAE mobile is `invalid` on `dncr` and is still screened for agents. If the registry cannot be reached, the whole request fails and no agent results are returned.



## OpenAPI

````yaml /api-reference/openapi.json post /public/phone-screening/check
openapi: 3.0.3
info:
  title: Provident — Lead Intake API
  version: 1.13.0
  description: >-
    Server-to-server API for pushing leads into the Provident CRM.


    Core endpoints:

    1. `POST /oauth2/token` — exchange client credentials for a bearer token.

    2. `POST /public/leads` — create a CRM lead.

    3. `PUT /public/leads/{id}` — add details you did not have when you created
    it (quiz answers the customer finished afterwards, a budget, an area). Send
    only what changed; phones and emails are appended, never replaced, and the
    lead's stage, status, owner and funnel are not writable.


    Both the create and the update body accept `comments[]` (max 5 per request,
    each with its own `date`), which writes a conversation that happened
    elsewhere onto the lead's thread; the response reports `comments: { added,
    skipped }` and going over the cap skips rather than fails.


    Optional read-only reference data, using the same token: locations,
    developers, projects and project statuses. Use them to send values that
    match ours, or to show project content on your own pages. They share the
    lead endpoint's rate limit, so cache them.


    Optional compliance check, using the same token: `POST /public/dncr/check`
    checks up to 20 UAE mobile numbers against the UAE Do Not Call Registry
    before you contact them. Answers are cached for 180 days, and `fresh: true`
    asks the registry again.


    Authentication is OAuth 2.0 Client Credentials; there is no user login. Note
    that the `/v2` prefix is part of the server URL and is mandatory.


    The intake is deliberately forgiving: name-based lookup fields that cannot
    be matched do NOT fail the request — the lead is still created and the
    unmatched values are returned in `intakeUnresolved`.


    The endpoint is not idempotent at the transport level, but intake hygiene
    runs before the lead is created: a second enquiry from the same phone/email
    for the same funnel within the merge window (~24h) is MERGED into the
    existing lead (its details are folded onto the lead add-only: languages
    added, phones/emails appended, empty fields filled, nothing overwritten;
    attribution stays the first enquiry's; an enquiry for a different funnel
    always becomes its own lead) and returns a different, much shorter 201 body
    — `{ id, merged: true, matchedOn }` — with no contactId, intakeUnresolved,
    needsIntakeReview or createdAt. Always branch on `merged` before reading
    anything else. Enquiries from property-portal sources (Property Finder,
    Bayut, Dubizzle) are exempt and never merge. Retry only on network timeouts,
    429 and 5xx.
  contact:
    name: Provident API support
servers:
  - url: https://devapi.prov.ae/v2
    description: Staging / development — build and test here
  - url: https://prodapi.prov.ae/v2
    description: Production — live leads
security: []
tags:
  - name: Authentication
    description: OAuth 2.0 client-credentials token issuance
  - name: Lead intake
    description: Public lead creation
  - name: Reference data
    description: Read-only lookups — locations, developers, projects, project statuses
  - name: Lead follow-up
    description: >-
      Reading back who a lead was assigned to, and recording the agent response
      time
  - name: Do Not Call Registry
    description: >-
      Check UAE mobile numbers against the Do Not Call Registry before
      contacting them
  - name: Phone screening
    description: >-
      Find which phone numbers belong to real-estate brokers or to Provident
      staff, to take them off a contact list
  - name: WhatsApp check
    description: Find out whether phone numbers are on WhatsApp before you message them
  - name: Webhooks
    description: >-
      Calls Provident makes to YOUR server. Documented here for the payload
      shape; these are not endpoints you call.
paths:
  /public/phone-screening/check:
    post:
      tags:
        - Phone screening
      summary: Screen numbers for DNCR, other agents, and our staff
      description: >-
        Runs the DNCR check, the broker-register check and the Provident-staff
        check on the same numbers, up to 20 (the DNCR limit). Enabled
        separately: access to this endpoint does not include the three separate
        ones, and access to them does not include this one. `ourAgent` says
        whether a number belongs to a Provident employee (current or former,
        work or personal) and never who. A number that is not a UAE mobile is
        `invalid` on `dncr` and is still screened for agents. If the registry
        cannot be reached, the whole request fails and no agent results are
        returned.
      requestBody:
        required: true
        content:
          application/json:
            schema:
              $ref: '#/components/schemas/ContactScreeningRequest'
            example:
              phones:
                - '0501234567'
                - +971 50 765 4321
              fresh: false
      responses:
        '200':
          description: One row per number sent, in the order sent, with all three answers.
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ContactScreeningResponse'
        '400':
          description: >-
            No numbers, or more than the DNCR batch size
            (`DNCR_TOO_MANY_NUMBERS`). Nothing was checked.
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ApiError'
        '401':
          $ref: '#/components/responses/Unauthorized'
        '403':
          $ref: '#/components/responses/Forbidden'
        '422':
          $ref: '#/components/responses/ValidationFailed'
        '429':
          $ref: '#/components/responses/RateLimited'
        '502':
          description: The Do Not Call Registry could not be reached. Nothing was answered.
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ApiError'
        '503':
          description: DNCR checks are not configured on this server.
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ApiError'
      security:
        - bearerAuth: []
components:
  schemas:
    ContactScreeningRequest:
      type: object
      required:
        - phones
      additionalProperties: false
      properties:
        phones:
          type: array
          minItems: 1
          maxItems: 20
          items:
            type: string
          description: >-
            Numbers to screen, at most 20 (the DNCR limit). Any spelling the
            broker check accepts. A non-UAE number is `invalid` on the DNCR side
            and is still screened for agents.
        fresh:
          type: boolean
          default: false
          description: >-
            Skip the 180-day DNCR cache and ask the registry again.
            `?fresh=true` does the same.
    ContactScreeningResponse:
      type: object
      required:
        - data
        - meta
      properties:
        data:
          type: array
          items:
            type: object
            required:
              - input
              - dncr
              - possibleAgent
              - ourAgent
            properties:
              input:
                type: string
                description: The number exactly as sent.
              dncr:
                type: object
                description: >-
                  The DNCR answer for this number. Same fields as a DNCR result,
                  without a second copy of `input`.
                required:
                  - phone
                  - e164
                  - status
                  - onDncr
                properties:
                  phone:
                    type: string
                    nullable: true
                  e164:
                    type: string
                    nullable: true
                  status:
                    type: string
                    enum:
                      - registered
                      - not_registered
                      - not_found
                      - invalid
                      - unavailable
                  onDncr:
                    type: boolean
                    nullable: true
                  dncrStatus:
                    type: string
                    nullable: true
                  etisalatStatus:
                    type: string
                    nullable: true
                  checkedAt:
                    type: string
                    format: date-time
                    nullable: true
                  source:
                    type: string
                    nullable: true
                    enum:
                      - cache
                      - fresh
                  error:
                    type: string
                    nullable: true
              possibleAgent:
                type: object
                required:
                  - phone
                  - status
                  - matchCount
                  - matches
                properties:
                  phone:
                    type: string
                    nullable: true
                  status:
                    type: string
                    enum:
                      - match
                      - no_match
                      - invalid
                  matchCount:
                    type: integer
                  matches:
                    type: array
                    items:
                      $ref: '#/components/schemas/BrokerMatch'
              ourAgent:
                type: object
                required:
                  - phone
                  - status
                  - currentEmployee
                properties:
                  phone:
                    type: string
                    nullable: true
                  status:
                    type: string
                    enum:
                      - match
                      - no_match
                      - invalid
                    description: >-
                      A Provident employee number, current or former. Never says
                      who.
                  currentEmployee:
                    type: boolean
        meta:
          type: object
          required:
            - requested
            - maxNumbersPerRequest
            - dncr
            - possibleAgent
            - ourAgent
          properties:
            requested:
              type: integer
            maxNumbersPerRequest:
              type: integer
              example: 20
            dncr:
              type: object
            possibleAgent:
              type: object
            ourAgent:
              type: object
    ApiError:
      type: object
      description: Common error envelope used by every endpoint.
      properties:
        statusCode:
          type: integer
          example: 400
        code:
          type: string
          description: >-
            Stable machine-readable error code — branch on this, not on
            `message`.
          example: BAD_REQUEST
        message:
          type: string
          description: Human-readable description.
        errors:
          type: array
          items:
            type: string
          description: 'Present on 422 only: one entry per field that failed validation.'
        details:
          type: object
          additionalProperties: true
          description: Optional structured extras attached by the failing handler.
        path:
          type: string
          example: /v2/public/leads
        timestamp:
          type: string
          format: date-time
    BrokerMatch:
      type: object
      properties:
        source:
          type: string
          enum:
            - bb
            - dld
          description: >-
            `dld` is the Dubai Land Department broker register; `bb` is a second
            broker list.
        brokerName:
          type: string
          nullable: true
        brokerNameAr:
          type: string
          nullable: true
          description: '`dld` records only.'
        companyName:
          type: string
          nullable: true
          description: Agency name, `bb` records only.
        brokerNumber:
          type: string
          nullable: true
          description: RERA / DLD broker number.
        realEstateNumber:
          type: string
          nullable: true
          description: The agency's licence number.
        licenseEndDate:
          type: string
          format: date
          nullable: true
          description: '`dld` records only.'
  responses:
    Unauthorized:
      description: Missing, invalid, revoked or expired bearer token.
      content:
        application/json:
          schema:
            $ref: '#/components/schemas/ApiError'
          example:
            statusCode: 401
            code: OAUTH_TOKEN_EXPIRED
            message: OAuth access token expired
            path: /v2/public/projects/filters
            timestamp: '2026-07-27T06:31:04.512Z'
    Forbidden:
      description: >-
        Your credentials are not enabled for this endpoint (or your IP is not on
        the client's allowlist).
      content:
        application/json:
          schema:
            $ref: '#/components/schemas/ApiError'
          example:
            statusCode: 403
            code: OAUTH_CLIENT_GRANT_MISSING
            message: >-
              This client is not allowed to use this endpoint. It needs the
              "client:dncr:check:create" grant.
            details:
              requiredGrant: client:dncr:check:create
            path: /v2/public/dncr/check
            timestamp: '2026-10-06T12:00:00.000Z'
    ValidationFailed:
      description: >-
        A parameter or field failed validation. Note that an UNRECOGNISED query
        parameter is rejected, not ignored — this is how a call written against
        the old `page`-based developers endpoint now fails. Fix the request;
        never retry it unchanged.
      content:
        application/json:
          schema:
            $ref: '#/components/schemas/ApiError'
          example:
            statusCode: 422
            code: VALIDATION_ERROR
            message: Validation failed
            errors:
              - property page should not exist
            path: /v2/public/developers?page=1&limit=2
            timestamp: '2026-08-19T07:20:28.507Z'
    RateLimited:
      description: >-
        Request quota for this client exceeded. Wait `Retry-After` seconds, then
        resume.
      headers:
        Retry-After:
          description: Seconds to wait before retrying.
          schema:
            type: integer
        X-RateLimit-Limit:
          $ref: '#/components/headers/XRateLimitLimit'
        X-RateLimit-Remaining:
          $ref: '#/components/headers/XRateLimitRemaining'
        X-RateLimit-Reset:
          $ref: '#/components/headers/XRateLimitReset'
      content:
        application/json:
          schema:
            $ref: '#/components/schemas/ApiError'
          example:
            statusCode: 429
            code: RATE_LIMITED
            message: Too Many Requests
            path: /v2/public/leads
            timestamp: '2026-07-27T06:31:04.512Z'
  headers:
    XRateLimitLimit:
      description: Requests allowed in the current window.
      schema:
        type: integer
    XRateLimitRemaining:
      description: Requests remaining in the current window.
      schema:
        type: integer
    XRateLimitReset:
      description: Seconds until the counter resets (end of the UTC day).
      schema:
        type: integer
  securitySchemes:
    bearerAuth:
      type: http
      scheme: bearer
      bearerFormat: Opaque
      description: >-
        The `access_token` returned by `POST /oauth2/token`, sent as
        `Authorization: Bearer <access_token>`. It is an opaque string, not a
        JWT.

````

This documentation is built and hosted on [Mintlify](https://mintlify.com), a developer documentation platform.