<?xml version="1.0" encoding="utf-8"?>
<!--
  numbers.online — 3CX server-side CRM integration template
  =========================================================

  What it does
    Adds numbers.online as a server-side CRM lookup source for inbound calls.
    When a call arrives from a number that is NOT already a 3CX contact, 3CX
    queries numbers.online and, if a business caller-name (CNAM) is available,
    shows it on the call. This resolves otherwise-unknown inbound callers to a
    name, tenant-wide, with no client-side software.

  Install path (3CX Admin Console)
    Settings > CRM > Server side > Add > upload this file > paste your API key
    into the "numbers.online API Key" field > Save, then RESTART the 3CX System
    Service (template/CRM changes require a service restart to take effect).
    Full guide: https://numbers.online/integrations

  Data positioning (read before deploying)
    The CNAM returned here is a SUPPLEMENTARY SIGNAL derived from wholesale CNAM
    and number-range data. It is advisory, may be absent or stale, and is not an
    authoritative identity. Your operator keeps the routing decision. This
    template is provided AS-IS, with no warranty, under the numbers.online terms
    at https://numbers.online/docs.

  Compatibility: 3CX V18 and V20 (identical server-side CRM template format).
-->
<Crm Name="numbers.online" Version="1" Country="US" SupportsEmojis="false">

  <!-- [Number] resolves to the caller's number in +E.164 form, which is what
       the numbers.online API path segment expects. -->
  <Number Prefix="Plus" MaxLength="" />

  <!-- Inbound CNAM lookups are short and bursty; keep concurrency conservative. -->
  <Connection MaxConcurrentRequests="2" />

  <!-- Admin-editable fields shown in the Admin Console after upload. -->
  <Parameters>
    <Parameter Name="ApiKey"
               Type="Password"
               Parent="General Configuration"
               Editor="String"
               Title="numbers.online API Key"
               Default=""
               Validation=".+" />
  </Parameters>

  <!-- The bearer key is sent as a per-request Authorization header
       (Authentication Type="No" + a static Headers block). -->
  <Authentication Type="No" />

  <Scenarios>
    <!-- An EMPTY Scenario Id is the inbound phone-number lookup scenario. -->
    <Scenario Id="" Type="REST">
      <Request SkipIf=""
               Url="https://numbers.online/v1/lookup/[Number]"
               RequestEncoding="UrlEncoded"
               RequestType="Get"
               ResponseType="Json">
        <Headers>
          <Value Key="Authorization">Bearer [ApiKey]</Value>
        </Headers>
      </Request>

      <!-- Only treat the response as a contact when a caller-name is present.
           A null/absent cnam means "no name" — the rule fails to match and 3CX
           falls back to showing the raw number (fail-open). -->
      <Rules>
        <Rule Type="Any">cnam</Rule>
      </Rules>

      <!-- The cnam field is a JSON STRING, so Path="cnam" captures it directly. -->
      <Variables>
        <Variable Name="CnamName" Path="cnam">
          <Filter />
        </Variable>
      </Variables>

      <!-- A 3CX contact only registers when ContactUrl + a name field
           (CompanyName here) + a phone output equal to the searched number are
           ALL present, so all three are emitted. PhoneBusiness MUST echo the
           searched number byte-identically. -->
      <Outputs AllowEmpty="false">
        <Output Type="CompanyName" Value="[CnamName]" />
        <Output Type="PhoneBusiness" Value="[Number]" />
        <Output Type="ContactUrl" Value="https://numbers.online/lookup/[Number]" />
        <Output Type="EntityId" Value="[Number]" />
        <Output Type="EntityType" Value="Contacts" />
      </Outputs>
    </Scenario>
  </Scenarios>

</Crm>
