> ## 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.

# Get an Analysis Request

> Where a requested analysis stands. Only the account that made the
request, or one that joined it, can read it; any other id gets
`404`.

Poll every minute or two. A `scheduled` request won't start before
`scheduled_for`, so poll it less often until then. When `status` is
`complete`, `determination` has the published status and
`links.compliance` the full result. A request still `under_review`
after `promised_by` is with our team. If you sent `"notify": true`, we
will email the account when we publish the result, so you can stop
polling then.




## OpenAPI

````yaml GET /analysis-requests/{request_id}
openapi: 3.1.0
info:
  title: halal.sh API
  version: 1.0.0
  description: |
    The halal.sh API screens public equities and ETFs for Shariah compliance,
    based on AAOIFI Shari'ah Standard No. 21.

    Every determination includes 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: each
    screen's calculation, the values it used and the filing they came from.

    ## 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's description states its unit.
    - **Status**: compliance status is always `compliant`, `non-compliant`, or
      `pending`. Treat unknown future values as `pending`.
    - **Money**: amounts are in US dollars, converted for a company that reports
      in another currency.
  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: Analysis requests
    description: >-
      Ask for an analysis of a stock we haven't screened yet, and follow it to
      the result.
  - 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.
  - name: Account
    description: Who is calling, on what plan, and where everything is.
paths:
  /analysis-requests/{request_id}:
    get:
      tags:
        - Analysis requests
      summary: Get an analysis request
      description: |
        Where a requested analysis stands. Only the account that made the
        request, or one that joined it, can read it; any other id gets
        `404`.

        Poll every minute or two. A `scheduled` request won't start before
        `scheduled_for`, so poll it less often until then. When `status` is
        `complete`, `determination` has the published status and
        `links.compliance` the full result. A request still `under_review`
        after `promised_by` is with our team. If you sent `"notify": true`, we
        will email the account when we publish the result, so you can stop
        polling then.
      operationId: getAnalysisRequest
      parameters:
        - name: request_id
          in: path
          required: true
          description: The `request_id` from `POST /analysis-requests`.
          schema:
            type: string
            format: uuid
      responses:
        '200':
          description: The request
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/AnalysisRequestResponse'
        '401':
          $ref: '#/components/responses/Unauthorized'
        '404':
          $ref: '#/components/responses/NotFound'
        '429':
          $ref: '#/components/responses/RateLimited'
components:
  schemas:
    AnalysisRequestResponse:
      type: object
      properties:
        data:
          $ref: '#/components/schemas/AnalysisRequest'
        meta:
          $ref: '#/components/schemas/Meta'
    AnalysisRequest:
      type: object
      required:
        - request_id
        - instrument_id
        - status
        - lane
        - requested_at
        - promised_by
        - scheduled_for
        - completed_at
        - progress_percentage
        - determination
        - notify
        - links
      properties:
        request_id:
          type: string
          format: uuid
        instrument_id:
          type: string
          description: >-
            The listing the request is for, in the form `/instruments/{symbol}`
            accepts.
          example: TYO:7203
        status:
          type: string
          enum:
            - queued
            - scheduled
            - running
            - under_review
            - complete
          description: |
            - `queued`: waiting to start.
            - `scheduled`: on the Standard lane, waiting for `scheduled_for`.
            - `running`: we're analyzing it.
            - `under_review`: with our compliance team before we publish the
              result. Every fund and trust goes through it, and so does a run
              that hits a problem, which the team then finishes.
            - `complete`: published. `determination` has the status.

            Treat an unknown future value as still in progress.
        lane:
          type: string
          enum:
            - priority
            - standard
          description: >-
            `priority` starts now, and we promise it within 2 hours. `standard`
            waits for a window, and we promise it within 2 days.
        requested_at:
          type: string
          format: date-time
          nullable: true
        promised_by:
          type: string
          format: date-time
          nullable: true
          description: When we said the analysis would be ready.
        scheduled_for:
          type: string
          format: date-time
          nullable: true
          description: >-
            When a Standard-lane request starts. Null on the Priority lane, and
            once the request is under review or complete.
        completed_at:
          type: string
          format: date-time
          nullable: true
          description: When we saved the result. Null until `status` is `complete`.
        progress_percentage:
          type: integer
          minimum: 0
          maximum: 100
          description: How far the analysis has got, as a whole-number percentage.
        determination:
          type: string
          enum:
            - compliant
            - non-compliant
            - pending
          nullable: true
          description: >-
            The published compliance status once `status` is `complete`, else
            null.
        notify:
          type: boolean
          description: >-
            Whether we will email you about this request, as you set it with
            `notify`.
        links:
          type: object
          required:
            - self
            - compliance
          properties:
            self:
              type: string
              example: /v1/analysis-requests/6f1c2d4e-0000-4000-8000-000000000001
            compliance:
              type: string
              example: /v1/instruments/TYO:7203/compliance
    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.

            `aaoifi-ss21` for an operating company; `aaoifi-ss57`, `aaoifi-ss20`
            or

            `halal-sh-etf-taxonomy` for a pooled vehicle decided on its
            structure

            (see `screens.structural` on the compliance resource).
          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
                - plan_required
                - not_found
                - already_analyzed
                - listing_not_active
                - no_filings
                - stale_filings
                - withheld
                - rate_limit_exceeded
                - analysis_limit_reached
                - service_unavailable
                - internal_error
              example: not_found
            message:
              type: string
              example: Stock with identifier 'XYZ' not found
            retry_after:
              type: integer
              description: Seconds until you can retry (only on 429).
            limit_type:
              type: string
              enum:
                - daily
                - in_progress
              description: >-
                On `analysis_limit_reached`: which part of the allowance is used
                up, the day's analyses or those running at once.
            limit:
              type: integer
              description: 'On `analysis_limit_reached`: the allowance.'
            current:
              type: integer
              description: 'On `analysis_limit_reached`: how many you have used.'
            reset_at:
              type: string
              format: date-time
              description: 'On `analysis_limit_reached`: when you can ask again.'
            instrument_id:
              type: string
              description: >-
                On `already_analyzed` for a secondary share class: the primary,
                whose result applies.
            status:
              type: string
              description: >-
                On `listing_not_active`: the listing's status, such as
                `delisted`.
            delisted_at:
              type: string
              format: date-time
              nullable: true
              description: 'On `listing_not_active`: the date of the delisting.'
            upgrade:
              $ref: '#/components/schemas/UpgradeOffer'
        meta:
          $ref: '#/components/schemas/Meta'
    UpgradeOffer:
      type: object
      description: |
        The paid plans that remove a sandbox limit, with their prices. Present
        on every `sandbox_restricted` 403 and on a sandbox caller's 429, and
        absent for a caller already on a paid plan.
      required:
        - plan
        - price_usd_monthly
        - url
        - commercial_plan
        - commercial_price_usd_monthly
        - commercial_url
      properties:
        plan:
          type: string
          enum:
            - plus
          description: 'The plan for your own use: live keys, the full universe, MCP.'
        price_usd_monthly:
          type: number
          example: 7
        url:
          type: string
          format: uri
          example: https://halal.sh/plans?source=api_refusal
        commercial_plan:
          type: string
          enum:
            - developer
          description: The plan for showing results in your own product.
        commercial_price_usd_monthly:
          type: number
          example: 99
        commercial_url:
          type: string
          format: uri
          example: https://halal.sh/developers
  responses:
    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
    NotFound:
      description: Resource not found
      content:
        application/json:
          schema:
            $ref: '#/components/schemas/ErrorResponse'
          example:
            error:
              code: not_found
              message: Stock with identifier 'XYZ' not found
            meta:
              request_id: req_abc123
    RateLimited:
      description: >
        Rate limit exceeded: your plan's daily or per-minute allowance, or a

        per-IP limit (600 a minute on every request before its key is checked,

        60 a minute on the index and the OpenAPI document). Developer limits

        are per account: every live key, connected app and signed-in session on

        the account shares them. On the Plus plan, limits apply to each live key
        separately.

        `Retry-After` and `error.retry_after` give the wait in seconds

        whichever limit refused. A sandbox caller's 429 also has

        `error.upgrade`, and its `message` says what the Plus plan includes

        and costs.
      headers:
        X-RateLimit-Limit:
          schema:
            type: integer
          description: >-
            Maximum requests allowed in the current window (a day for your
            plan's allowance, a minute for the per-IP limits).
        X-RateLimit-Remaining:
          schema:
            type: integer
          description: Requests remaining in the current window.
        X-RateLimit-Reset:
          schema:
            type: string
            format: date-time
          description: ISO 8601 timestamp when the current window resets.
        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 limit of 100 requests reached. It resets at midnight UTC.
                The Plus plan includes up to 2,000 requests a day on every stock
                and ETF we cover, for $7 a month:
                https://halal.sh/plans?source=api_refusal. To show results in
                your own product, you need the Developer plan, at $99 a month:
                https://halal.sh/developers.
              retry_after: 3600
              upgrade:
                plan: plus
                price_usd_monthly: 7
                url: https://halal.sh/plans?source=api_refusal
                commercial_plan: developer
                commercial_price_usd_monthly: 99
                commercial_url: https://halal.sh/developers
            meta:
              request_id: req_abc123
  securitySchemes:
    apiKey:
      type: apiKey
      in: header
      name: X-API-Key

````

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