---
title: "Submit credential for anchoring"
method: POST
path: "/anchor/submit"
tags: ["Anchoring"]
---

# Submit credential for anchoring

`POST /anchor/submit`

## Request

- Base URL: `https://app.arkova.ai/api/v1`
- URL: `https://app.arkova.ai/api/v1/anchor/submit`
- Auth: one of:
  - HTTP bearer
  - API key in header `X-API-Key`

Compatibility alias for POST /anchor. New integrations should use POST /anchor.

## Request body

- object
  - `fingerprint` string, required: SHA-256 document fingerprint (64-char hex; normalized to lowercase)
  - `receipt_id` string, uuid: Completed extraction receipt. Requires request_id and matching fingerprint; stored extraction fields are consumed server-side.
  - `request_id` string, uuid: Stable submission UUID, distinct from extraction requestId. Required with receipt_id. Replay unchanged input after an uncertain response; changed input conflicts.
  - `filename` string: Receipt submission basename only; never a local path.
  - `file_size` integer: Original document size in bytes for receipt submission.
  - `file_mime` string
  - `label` string, nullable: Optional legacy record label, stored separately from filename and description. It can appear in public credential projections; do not include personal or confidential data. Omit it or pass null when no label is needed.
  - `description` string: Public document description included in verification responses (at most 500 characters)
  - `credential_type` 'DEGREE' | 'LICENSE' | 'CERTIFICATE' | 'TRANSCRIPT' | 'PROFESSIONAL' | 'CPE' | 'CLE' | 'BADGE' | 'ATTESTATION' | 'FINANCIAL' | 'LEGAL' | 'INSURANCE' | 'SEC_FILING' | 'PATENT' | 'REGULATION' | 'PUBLICATION' | 'CHARITY' | 'ACCREDITATION' | 'FINANCIAL_ADVISOR' | 'BUSINESS_ENTITY' | 'RESUME' | 'MEDICAL' | 'MILITARY' | 'IDENTITY' | 'CONTRACT_PRESIGNING' | 'CONTRACT_POSTSIGNING' | 'OTHER' | 'DIPLOMA': DIPLOMA is a legacy input alias stored as DEGREE; responses use the canonical credential type.
  - `action` 'queue' | 'instant': Queue for batch anchoring or reserve one anchor credit to start now
  - `private_tags` object: Private tags; never included in public records or webhook payloads
    - `user` string[]
    - `organization` string[]
  - `metadata` object: PII-stripped metadata fields

## Response `200`

Existing caller-owned submission (idempotent)

- object
  - `public_id` string, required
  - `fingerprint` string, required
  - `status` string, required: Record lifecycle: PENDING means accepted for processing; SUBMITTED means sent to the network; SECURED means confirmed. Acceptance is not proof of confirmation. An idempotent response returns the current record status.
  - `created_at` string, date-time, required
  - `record_uri` string, uri, required
  - `action` 'queue' | 'instant', required
  - `credits_exempt` boolean, nullable: True when the durable Instant claim used an actor usage exemption; credit_state is null because no credit was spent or refunded.
  - `credit_state` 'pending' | 'spent' | 'refunded', nullable, required
  - `instant_status` 'QUEUED' | 'PROCESSING' | 'NEEDS_CREDIT' | 'RETRYABLE' | 'HELD' | 'SUBMITTED' | 'FAILED', nullable, required: Instant-processing state, separate from record status. null: normal queue with no instant intent. QUEUED: accepted, waiting for a worker. PROCESSING: worker owns the attempt. NEEDS_CREDIT: add a credit before retrying instant processing. RETRYABLE: a safe retry is available. HELD: uncertain network outcome; poll status and do not create a new record. SUBMITTED: sent, awaiting network confirmation. FAILED: instant attempt ended; inspect submission status before retrying. Example: status=PENDING, instant_status=NEEDS_CREDIT means the record was accepted but instant processing needs credit; status=SUBMITTED, instant_status=SUBMITTED is not yet SECURED.
  - `idempotent` boolean, required

## Other responses

- `201`: Anchor created
- `400`: Invalid request
- `401`: Authentication required
- `402`: Payment required (x402)
- `403`: The authenticated caller lacks anchor write scope, cannot act for the selected organization, or the selected organization is suspended.
- `409`: The fingerprint already belongs to another scope for this actor, supplied private tags differ from the immutable tags on an idempotent submission, or anchor creation encountered a generic uniqueness conflict. No existing public_id is disclosed. Do not retry unchanged: for submission_metadata_conflict restore the original private tags (or omit them); for fingerprint_conflict use the original caller and organization; for anchor_creation_conflict contact support. A duplicate in the same caller and organization scope with compatible private tags returns 200 with idempotent: true.
- `429`: The request-rate limit, legacy organization daily quota, or current billing-period anchor allowance was exhausted. X-Org-Quota-* headers describe only the legacy daily quota. A billing allowance response uses its actual period end when available.
- `500`: Anchor creation failed without exposing database or provider details.
- `503`: Submission, organization, quota, metadata, or instant-processing state is temporarily unavailable. organization_unavailable means the organization lookup could not supply a supported quota policy; it does not mean the API key is invalid or the organization is suspended. quota_check_failed means quota service state could not be read, not that usage is exhausted. Retry transient failures with backoff; contact support if persistent. A known suspended organization is a separate 403 org_suspended response.

---

[API](https://skmtc.dev/arkova/apis/arkova-verification-api.md) · [All operations](https://skmtc.dev/arkova/apis/arkova-verification-api/llms.txt) · [OpenAPI document](https://skmtc.dev/arkova/apis/arkova-verification-api/revisions/a14858d1efd4?raw)
