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

# Search Instruments

> Search stocks **and ETFs** by ticker or company/fund name. Returns `200`
with an empty array when nothing matches.

Every item carries a `type` discriminator (`stock` | `etf`). Stock items
include a compliance `status`; ETF items instead expose Shariah purity
(`purity_percentage`, `badge_color`) and `match_coverage_percent`, and
carry **no** `status` field. Use the `types` parameter to filter to one
kind — omit it to receive both.


Search returns **both stocks and ETFs**. Every item carries a `type`
discriminator so you can branch on it:

* **`type: "stock"`** — includes a compliance `status`
  (`compliant` | `non-compliant` | `pending`) and `last_analyzed_at`.
* **`type: "etf"`** — includes Shariah purity (`purity_percentage` and
  `badge_color`) plus `match_coverage_percent`, and carries **no** `status`
  field. An ETF's purity is deliberately not collapsed into a binary
  compliant/non-compliant verdict. Route ETF hits to
  [Get an ETF](/api-reference/etfs/get-etf) for the full holdings-based
  breakdown.

<Note>
  `match_coverage_percent` is the percent of fund weight whose holdings are
  matched to a screened instrument — it is **match coverage, not screened
  coverage**. Do not present it as "% screened". `purity_percentage` /
  `badge_color` are the screened verdict and are `null` until the ETF has been
  screened.
</Note>

## Filtering by type

The optional `types` query parameter narrows results to one kind:

* `types=stock` — stocks only (the pre-ETF response shape).
* `types=etf` — ETFs only.
* Omitted — both (the default).

`types` is comma-separated and allow-list validated: any value other than
`stock` or `etf` returns `400 Bad Request`.


## OpenAPI

````yaml GET /search
openapi: 3.1.0
info:
  title: halal.sh API
  version: 1.0.0
  description: >
    The halal.sh API provides Shariah compliance screening for public equities

    and ETFs, based on AAOIFI Shari'ah Standard No. 21.


    Unlike a black-box verdict, every determination exposes the individual

    screens, the financial ratios with their thresholds, the revenue breakdown,

    and the source filings behind each number. The Evidence Packet endpoint

    returns the full audit trail — accession numbers, XBRL tags, and extraction

    strategies — for compliance, reporting, and reproducibility.


    ## Conventions


    - **Base URL** — `https://api.halal.sh/v1`

    - **Authentication** — send your key in the `X-API-Key` header.

    - **Envelope** — every success response is `{ "data": …, "meta": … }`. Every
      error is `{ "error": { "code", "message" } }`.
    - **Ratios** — screen `value`, `threshold`, and `buffer` are decimals
      (`0.082` means 8.2%, `0.30` means 30%). Fields named `*percentage`,
      `purity.percentage`, and holding `weight` are whole-number percentages
      (`66.74` means 66.74%). Each field documents its unit.
    - **Status** — compliance status is always `compliant`, `non-compliant`, or
      `pending`. Treat unknown future values as `pending`.
    - **Money** — values are in the instrument's reporting currency (USD for US
    filers).
  contact:
    name: halal.sh API support
    url: https://halal.sh/developers
    email: api@halal.sh
servers:
  - url: https://api.halal.sh/v1
    description: Production
security:
  - apiKey: []
tags:
  - name: Instruments
    description: Compliance, financials, evidence, history, and health for a single stock.
  - name: Screening
    description: Batch screening and search across the instrument universe.
  - name: ETFs
    description: Shariah purity and holdings breakdown for ETFs.
  - name: Methodology
    description: The screening methodology, its thresholds, and version.
paths:
  /search:
    get:
      tags:
        - Screening
      summary: Search instruments
      description: |
        Search stocks **and ETFs** by ticker or company/fund name. Returns `200`
        with an empty array when nothing matches.

        Every item carries a `type` discriminator (`stock` | `etf`). Stock items
        include a compliance `status`; ETF items instead expose Shariah purity
        (`purity_percentage`, `badge_color`) and `match_coverage_percent`, and
        carry **no** `status` field. Use the `types` parameter to filter to one
        kind — omit it to receive both.
      operationId: searchInstruments
      parameters:
        - name: q
          in: query
          required: true
          description: Search query (ticker or company/fund name).
          schema:
            type: string
            minLength: 1
            example: nvidia
        - name: limit
          in: query
          schema:
            type: integer
            default: 10
            minimum: 1
            maximum: 100
        - name: types
          in: query
          description: >-
            Comma-separated instrument-type filter. Allowed values: `stock`,
            `etf`. Omitted returns both. Any unrecognised value returns `400`.
          schema:
            type: string
            example: stock
            etf: null
      responses:
        '200':
          description: Search results
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/SearchResponse'
        '400':
          $ref: '#/components/responses/BadRequest'
        '401':
          $ref: '#/components/responses/Unauthorized'
        '429':
          $ref: '#/components/responses/RateLimited'
components:
  schemas:
    SearchResponse:
      type: object
      properties:
        data:
          type: array
          items:
            oneOf:
              - $ref: '#/components/schemas/SearchStockItem'
              - $ref: '#/components/schemas/SearchEtfItem'
            discriminator:
              propertyName: type
              mapping:
                stock:
                  $ref: '#/components/schemas/SearchStockItem'
                etf:
                  $ref: '#/components/schemas/SearchEtfItem'
        meta:
          allOf:
            - $ref: '#/components/schemas/Meta'
            - type: object
              properties:
                total:
                  type: integer
                query:
                  type: string
    SearchStockItem:
      type: object
      description: A stock search hit. Carries the compliance `status`.
      properties:
        type:
          type: string
          enum:
            - stock
          example: stock
        symbol:
          type: string
          example: NVDA
        name:
          type: string
          example: NVIDIA Corporation
        country_code:
          type: string
          nullable: true
          example: US
        exchange:
          type: string
          nullable: true
          example: Nasdaq
        sector:
          type: string
          nullable: true
        industry:
          type: string
          nullable: true
        status:
          $ref: '#/components/schemas/ComplianceStatus'
        last_analyzed_at:
          type: string
          format: date-time
          nullable: true
    SearchEtfItem:
      type: object
      description: >-
        An ETF search hit. Carries Shariah purity instead of a compliance
        `status` — an ETF's purity is deliberately not collapsed into a binary
        compliant/non-compliant on the public API.
      properties:
        type:
          type: string
          enum:
            - etf
          example: etf
        symbol:
          type: string
          example: HLAL
        name:
          type: string
          example: Wahed FTSE USA Shariah ETF
        country_code:
          type: string
          nullable: true
          example: US
        exchange:
          type: string
          nullable: true
          example: Nasdaq
        fund_family:
          type: string
          nullable: true
          example: Wahed
        match_coverage_percent:
          type: number
          nullable: true
          description: >-
            Percent of fund weight whose holdings are matched to a screened
            instrument. This is MATCH coverage, not screened coverage — do not
            present it as "% screened".
          example: 99.2
        purity_percentage:
          type: number
          nullable: true
          description: >-
            Shariah purity verdict (percent of holdings by weight that are
            compliant) from the latest purity snapshot. `null` when the ETF has
            not been screened yet.
          example: 97.1
        badge_color:
          type: string
          nullable: true
          enum:
            - green
            - amber
            - grey
          description: Verdict badge colour derived from the screened purity snapshot.
          example: green
    Meta:
      type: object
      properties:
        request_id:
          type: string
          description: Unique ID for this request. Include it in support requests.
          example: req_abc123
        as_of:
          type: string
          format: date-time
          description: When this response was generated.
        methodology:
          type: string
          description: Methodology used, as `id@version`. Present on compliance responses.
          example: aaoifi-ss21@2026.1
    ErrorResponse:
      type: object
      required:
        - error
      properties:
        error:
          type: object
          required:
            - code
            - message
          properties:
            code:
              type: string
              enum:
                - bad_request
                - unauthorized
                - sandbox_restricted
                - not_found
                - rate_limit_exceeded
                - service_unavailable
                - internal_error
              example: not_found
            message:
              type: string
              example: No instrument found for symbol 'XYZ'.
            retry_after:
              type: integer
              description: Seconds until the rate limit resets (only on 429).
        meta:
          $ref: '#/components/schemas/Meta'
    ComplianceStatus:
      type: string
      enum:
        - compliant
        - non-compliant
        - pending
      description: |
        Compliance determination. `pending` means the instrument has not been
        analysed yet. This enum may gain values in future; treat any unknown
        value as `pending`.
  responses:
    BadRequest:
      description: Invalid request parameters
      content:
        application/json:
          schema:
            $ref: '#/components/schemas/ErrorResponse'
          example:
            error:
              code: bad_request
              message: Maximum 50 symbols per request.
            meta:
              request_id: req_abc123
    Unauthorized:
      description: Missing or invalid API key
      content:
        application/json:
          schema:
            $ref: '#/components/schemas/ErrorResponse'
          example:
            error:
              code: unauthorized
              message: Invalid or revoked API key.
            meta:
              request_id: req_abc123
    RateLimited:
      description: Rate limit exceeded
      headers:
        X-RateLimit-Limit:
          schema:
            type: integer
          description: Maximum requests allowed in the current daily window.
        X-RateLimit-Remaining:
          schema:
            type: integer
          description: Requests remaining in the current daily window.
        X-RateLimit-Reset:
          schema:
            type: string
            format: date-time
          description: ISO 8601 timestamp when the daily window resets (midnight UTC).
        Retry-After:
          schema:
            type: integer
          description: Seconds to wait before retrying.
      content:
        application/json:
          schema:
            $ref: '#/components/schemas/ErrorResponse'
          example:
            error:
              code: rate_limit_exceeded
              message: Daily request limit (100) exceeded. Resets at midnight UTC.
              retry_after: 3600
            meta:
              request_id: req_abc123
  securitySchemes:
    apiKey:
      type: apiKey
      in: header
      name: X-API-Key

````