openapi: 3.0.3
info:
  title: daat.red API
  version: "1.0"
  description: >-
    Pre-authorization payment-data and identity-verification checks.
    Every method is a single request with an X-API-Key header; bodies and
    responses are UTF-8 JSON. You are charged only for useful results;
    failed and throttled calls cost 0 credits. Full reference: https://daat.red/docs
  contact:
    name: daat.red
    email: support@daat.red
    url: https://daat.red
servers:
  - url: https://api.daat.red
security:
  - ApiKeyAuth: []
tags:
  - name: Checks
  - name: Async

paths:
  /public/card:
    post:
      tags: [Checks]
      summary: Card check — verify the cardholder name with the card network
      operationId: cardCheck
      requestBody:
        required: true
        content:
          application/json:
            schema:
              type: object
              required: [cardNum, expMonth, expYear, nameOnCard]
              properties:
                cardNum: { type: string, description: Card number (PAN). Not stored. }
                expMonth: { type: string, example: "05" }
                expYear: { type: string, example: "2029" }
                nameOnCard: { type: string, description: "Order: Surname First name", example: "Doe John" }
                cryptogramType: { type: string, description: "For network tokens, e.g. TAVV, DSRP, AAV, UCAF" }
                cryptogramValue: { type: string, description: Token cryptogram. Never echoed back. }
                outInfo: { $ref: '#/components/schemas/OutInfo' }
      responses:
        '200':
          description: Verification result
          content:
            application/json:
              schema:
                allOf:
                  - $ref: '#/components/schemas/Common'
                  - type: object
                    properties:
                      status: { type: string, enum: [ok, not_valid, provider_err] }
                      cardLast4: { type: string }
                      bin: { type: string }
                      providerAsiCheckResult: { type: string, example: "A" }
                      providerAsiCheckName: { type: string, example: "Match" }
                      providerAsiCheckDescription: { type: string }
        '400': { $ref: '#/components/responses/BadRequest' }
        '401': { $ref: '#/components/responses/Unauthorized' }
        '402': { $ref: '#/components/responses/PaymentRequired' }
        '429': { $ref: '#/components/responses/TooManyRequests' }

  /public/card-info:
    post:
      tags: [Checks]
      summary: Card info — issuer, country, currency and product metadata by PAN
      operationId: cardInfo
      requestBody:
        required: true
        content:
          application/json:
            schema:
              type: object
              required: [cardNum]
              properties:
                cardNum: { type: string, description: Card number (PAN). Not stored. }
                outInfo: { $ref: '#/components/schemas/OutInfo' }
      responses:
        '200':
          description: Card metadata
          content:
            application/json:
              schema:
                allOf:
                  - $ref: '#/components/schemas/Common'
                  - type: object
                    properties:
                      status: { type: string, enum: [ok, not_valid] }
                      cardLast4: { type: string }
                      bin: { type: string }
                      issuerName: { type: string }
                      country:
                        type: object
                        properties:
                          code: { type: string }
                          numericCode: { type: string }
                          name: { type: string }
                      currency:
                        type: object
                        properties:
                          code: { type: string }
                          numericCode: { type: string }
                          name: { type: string }
                          minorDigits: { type: string }
                      product:
                        type: object
                        properties:
                          type: { type: string }
                          subTypeCode: { type: string }
                          platformCode: { type: string }
        '400': { $ref: '#/components/responses/BadRequest' }
        '401': { $ref: '#/components/responses/Unauthorized' }
        '402': { $ref: '#/components/responses/PaymentRequired' }
        '429': { $ref: '#/components/responses/TooManyRequests' }

  /public/bin-info:
    post:
      tags: [Checks]
      summary: BIN lookup — country, issuer and local currency for a card BIN
      operationId: binLookup
      requestBody:
        required: true
        content:
          application/json:
            schema:
              type: object
              required: [bin]
              properties:
                bin: { type: string, description: "6 to 8 digits", example: "531260" }
                outInfo: { $ref: '#/components/schemas/OutInfo' }
      responses:
        '200':
          description: BIN data
          content:
            application/json:
              schema:
                allOf:
                  - $ref: '#/components/schemas/Common'
                  - type: object
                    properties:
                      status: { type: string, enum: [ok, not_valid] }
                      countryCode: { type: string }
                      countryName: { type: string }
                      issuerName: { type: string }
                      localCurrency:
                        type: object
                        properties:
                          code: { type: string }
                          name: { type: string }
        '400': { $ref: '#/components/responses/BadRequest' }
        '401': { $ref: '#/components/responses/Unauthorized' }
        '402': { $ref: '#/components/responses/PaymentRequired' }
        '429': { $ref: '#/components/responses/TooManyRequests' }

  /public/ip-info:
    post:
      tags: [Checks]
      summary: IP info — geolocation and network context for an IP address
      operationId: ipInfo
      requestBody:
        required: true
        content:
          application/json:
            schema:
              type: object
              properties:
                ip: { type: string, description: "IPv4 or IPv6; empty uses the effective client IP", example: "8.8.8.8" }
                outInfo: { $ref: '#/components/schemas/OutInfo' }
      responses:
        '200':
          description: IP data
          content:
            application/json:
              schema:
                allOf:
                  - $ref: '#/components/schemas/Common'
                  - type: object
                    properties:
                      ip: { type: string }
                      status: { type: string, enum: [ok, not_valid] }
                      countryCode: { type: string }
                      countryName: { type: string }
                      cityName: { type: string }
                      postalCode: { type: string }
                      timeZone: { type: string }
                      asn: { type: integer }
                      asnOrganization: { type: string }
                      geoNames:
                        type: object
                        properties:
                          currencyCode: { type: string }
                          currencyName: { type: string }
                          phonePrefix: { type: string }
                          postalCodeFormat: { type: string }
        '400': { $ref: '#/components/responses/BadRequest' }
        '401': { $ref: '#/components/responses/Unauthorized' }
        '402': { $ref: '#/components/responses/PaymentRequired' }
        '429': { $ref: '#/components/responses/TooManyRequests' }

  /public/email-info:
    post:
      tags: [Checks]
      summary: Email info — names associated with an email address
      operationId: emailInfo
      requestBody:
        required: true
        content:
          application/json:
            schema:
              type: object
              required: [email]
              properties:
                email: { type: string, format: email }
                outInfo: { $ref: '#/components/schemas/OutInfo' }
      responses:
        '200':
          description: Email profile data
          content:
            application/json:
              schema:
                allOf:
                  - $ref: '#/components/schemas/Common'
                  - type: object
                    properties:
                      email: { type: string }
                      emailNameCheck:
                        type: object
                        properties:
                          status: { type: string, enum: [found, not_found] }
                          match: { type: boolean }
                          names:
                            type: array
                            items:
                              type: object
                              properties:
                                value: { type: string }
                                count: { type: integer }
                          checkedAt: { type: string, format: date-time }
        '400': { $ref: '#/components/responses/BadRequest' }
        '401': { $ref: '#/components/responses/Unauthorized' }
        '402': { $ref: '#/components/responses/PaymentRequired' }
        '429': { $ref: '#/components/responses/TooManyRequests' }

  /public/email-check:
    post:
      tags: [Checks]
      summary: Email check — live SMTP deliverability probe
      operationId: emailCheck
      requestBody:
        required: true
        content:
          application/json:
            schema:
              type: object
              required: [email]
              properties:
                email: { type: string, format: email }
                outInfo: { $ref: '#/components/schemas/OutInfo' }
      responses:
        '200':
          description: Deliverability result
          content:
            application/json:
              schema:
                allOf:
                  - $ref: '#/components/schemas/Common'
                  - type: object
                    properties:
                      ok: { type: boolean }
                      email: { type: string }
                      result: { type: string, enum: [accepted, rejected] }
                      responseCode: { type: integer, example: 250 }
                      info: { type: string, example: "250 2.1.5 OK" }
                      error: { type: string }
        '400': { $ref: '#/components/responses/BadRequest' }
        '401': { $ref: '#/components/responses/Unauthorized' }
        '402': { $ref: '#/components/responses/PaymentRequired' }
        '429': { $ref: '#/components/responses/TooManyRequests' }

  /public/balance:
    get:
      tags: [Checks]
      summary: Balance — current prepaid credit balance for the API key
      operationId: balance
      parameters:
        - in: query
          name: outInfo
          required: false
          schema: { type: string, maxLength: 64 }
      responses:
        '200':
          description: Credit balance
          content:
            application/json:
              schema: { $ref: '#/components/schemas/Common' }
        '401': { $ref: '#/components/responses/Unauthorized' }
        '429': { $ref: '#/components/responses/TooManyRequests' }

  /public/jobs/card:
    post:
      tags: [Async]
      summary: Queue a Card check as an async job
      operationId: jobCard
      requestBody:
        required: true
        content:
          application/json:
            schema: { type: object, description: Same body as POST /public/card }
      responses:
        '202':
          description: Job accepted
          content:
            application/json:
              schema:
                type: object
                properties:
                  id: { type: string }
                  status: { type: string, enum: [queued, processing, done, failed] }

  /public/jobs/bin-info:
    post:
      tags: [Async]
      summary: Queue a BIN lookup as an async job
      operationId: jobBinInfo
      requestBody:
        required: true
        content:
          application/json:
            schema: { type: object, description: Same body as POST /public/bin-info }
      responses:
        '202':
          description: Job accepted
          content:
            application/json:
              schema:
                type: object
                properties:
                  id: { type: string }
                  status: { type: string, enum: [queued, processing, done, failed] }

  /public/jobs/{id}:
    get:
      tags: [Async]
      summary: Poll an async job; returns the result once complete
      operationId: jobStatus
      parameters:
        - in: path
          name: id
          required: true
          schema: { type: string }
      responses:
        '200':
          description: Job status and, once complete, the result payload
          content:
            application/json:
              schema:
                type: object
                properties:
                  id: { type: string }
                  status: { type: string, enum: [queued, processing, done, failed] }
                  result: { type: object, description: "The method response; present when status is done" }
        '401': { $ref: '#/components/responses/Unauthorized' }
        '404': { description: Unknown job id }

components:
  securitySchemes:
    ApiKeyAuth:
      type: apiKey
      in: header
      name: X-API-Key
  schemas:
    OutInfo:
      type: string
      maxLength: 64
      description: Printable-ASCII correlation string, returned unchanged.
    Credits:
      type: object
      properties:
        balance: { type: integer, description: Remaining credit balance after the call. }
        charged: { type: integer, description: Credits charged for this call (0 for failed or throttled calls). }
    Common:
      type: object
      properties:
        outInfo: { type: string }
        receivedAt: { type: string, format: date-time }
        credits: { $ref: '#/components/schemas/Credits' }
    Error:
      type: object
      properties:
        error: { type: string }
        message: { type: string }
        credits: { $ref: '#/components/schemas/Credits' }
  responses:
    BadRequest:
      description: Malformed request or missing required field
      content:
        application/json:
          schema: { $ref: '#/components/schemas/Error' }
          example: { error: bad_request, message: "bad request" }
    Unauthorized:
      description: Missing or invalid X-API-Key, or source IP not allow-listed
      content:
        application/json:
          schema: { $ref: '#/components/schemas/Error' }
          example: { error: unauthorized, message: "missing api key" }
    PaymentRequired:
      description: Insufficient credits
      content:
        application/json:
          schema: { $ref: '#/components/schemas/Error' }
          example: { error: payment_required, message: "insufficient credits", credits: { balance: 2, charged: 0 } }
    TooManyRequests:
      description: Throttled — retry after the Retry-After header. Costs 0 credits.
      headers:
        Retry-After:
          schema: { type: integer }
      content:
        application/json:
          schema: { $ref: '#/components/schemas/Error' }
          example: { error: too_many_requests, message: "rate limit exceeded" }
