OceanirDocs
API

API Reference

Complete reference for all Oceanir REST API endpoints. All endpoints require authentication via API key.

Base URL

https://oceanir.ai/api/v1

Authentication

Include your API key in the x-api-key header:

x-api-key: orc_...

Pricing and usage

Developer API access is self-serve. Starter and Pro include API access, and any account that has bought credits can use it. Create a personal key in Platform › API keys (also reachable from Settings › Developers). Organizational, client-facing, batch, and production integrations require an Enterprise agreement with organization-scoped credentials.

Successful calls use the same credits as the app, at the depth cost below: your subscription's monthly credits and any credit packs. API credits bought before October 2026 are spent first. Failed analyses are not charged. When the API balance is too low, the API returns HTTP 402. Contracted Enterprise overage is available only by written agreement.

There is no separate API allowance: an API call costs what the same analysis costs in the app. This developer allowance is for individual development, testing, and low-volume internal use; organizational and client-facing production integrations require Enterprise.

Cost per call

D1 · 1 creditQuick estimate
D2 · 2 creditsStandard analysis
D3 · 10 creditsDetailed analysis

Credit costs

Personal API calls use the account's credits, the same balance as the app. Organization-scoped Enterprise calls use the contracted organization pool. The request defaults to D1 when depth is omitted.

Geolocation analysisD1, Surface1Region-level coordinates
Geolocation analysisD2, Standard2Block-level radius with visual evidence chain
Geolocation analysisD3, Forensic10Street-level lock with full reasoning + contradiction flags
Property verificationSoon—Confirm a photo shows the property it claims to
Bulk analysisSoon—Process an image set in one submission

Example: the 75 credits a Pro developer can add in one month cover 7 D3 analyses with 5 credits remaining, 37 D2 analyses with 1 remaining, or 75 D1 analyses.

When Enterprise is required

The self-serve developer API is intentionally capped. Move to Enterprise when the integration represents an organization or becomes part of a production or client-delivery workflow.

✓ Volume beyond your plan's monthly credits
✓ More than one user or API key
✓ Batch, webhook, or shared case workflows
✓ Paid client deliverables, resale, DPA, or SLA requirements

Enterprise provides pooled organization credits, commercial-use rights, contracted limits, onboarding, and operational controls. Contact sales to scope an evaluation or production agreement.

Endpoints

POST/api/v1/geolocate
GET/api/v1/analyses
GET/api/v1/credits
GET/api/v1/usage
POST/api/v1/cases

POST /api/v1/geolocate

Submit one image, get ranked coordinates with confidence and visual reasoning. Authenticate with your key in Authorization: Bearer <key> or x-api-key: <key> — both work. For retry-safe execution and billing, reuse the same Idempotency-Key for every retry of one analysis. A completed retry replays the original response without another model call or credit debit; using that key with a different payload returns HTTP 409.

Request body (JSON)

image_b64stringone ofRaw base64-encoded JPEG/PNG without a data: URL prefix. Max 20MB.
image_urlstringone ofPublic URL to fetch the image from instead.
modelstringoptionalCurrently orca-1.5. Omit it or send exactly this value.
depthintegeroptional1 = Surface (region, 1 credit), 2 = Standard (block, 2), 3 = Forensic (street, 10). Default 1.
effortstringoptionalinstant | low | medium | high. How long the model reasons INSIDE the chosen depth. It can only LOWER the effort that depth normally runs (d1 low, d2 medium, d3 high); asking for more returns 422. Useful for staying inside a deadline: depth 3 runs for 70s at the median, so effort: "low" trades reasoning for the chance of an answer inside your timeout. It does not change which verification passes run, what the response contains, or the credit cost. Depth decides all three. Echoed back as effort.
batch_idstringoptionalNamed batch from the Platform console. It must be bound to the API key making this request.
scopeobjectoptionalPin the search to one city: { name, lat, lng, radius_km }. radius_km defaults to 60 and accepts 1 to 500. Omit scope entirely for a worldwide search, which is the default. The scope narrows where the model looks; it is never treated as evidence and never raises confidence. If the image carries hard contradicting evidence, wrong script on signage, a foreign plate format, the wrong driving side, or impossible terrain, the model overrides the scope, returns the honest estimate and reports scope_consistent: false. Invalid values return 422.

Example request

curl -X POST https://oceanir.ai/api/v1/geolocate \
  -H "Authorization: Bearer orc_YOUR_KEY" \
  -H "Idempotency-Key: your-unique-request-id" \
  -H "Content-Type: application/json" \
  -d '{
    "image_url": "https://example.com/street.jpg",
    "batch_id": "batch_YOUR_BATCH_ID",
    "depth": 2,
    "scope": { "name": "Lyon", "lat": 45.764, "lng": 4.836, "radius_km": 60 }
  }'

Illustrative D2 response

{
  "success": true,
  "analysis_id": "example-analysis-id",
  "location": {
    "latitude": 45.77,
    "longitude": 4.8459,
    "country": "France",
    "city": "Lyon",
    "neighborhood": "6th arrondissement",
    "address": "Lyon, France"
  },
  "confidence": 0.79,
  "reasoning": "Street signage and architecture suggest Lyon. Confirm the area with independent evidence.",
  "visual_clues": [
    {
      "label": "French street signage",
      "detail": ""
    },
    {
      "label": "Stone facades",
      "detail": ""
    }
  ],
  "model": "orca-1.5",
  "depth": 2,
  "timing_ms": 9120
}

confidence is 0–1. thinking and visual_clues are returned only at depth ≥ 2. Each clue is { label, detail }. The detail may be empty. Image coordinates and contours are optional and appear only when available; integrations must also handle clues without them.

The forensic object (depth 3 only)

At depth 3 the response carries an additional forensic object. This is what separates a forensic call from a standard one: instead of a single coordinate, you get the evidence the conclusion rests on, the evidence that argues against it, and the alternative locations that were considered and rejected. It is designed to be shown to a reviewer, not just consumed by a program.

precision_tierstringHow tightly the location is resolved: exact, site_level, neighborhood_level, city_level or region_level.
verification_statusstringWhether the conclusion was corroborated, partially corroborated, or left unverified.
supportsstring[]Specific visual evidence that argues FOR the returned location. Signage, architecture, road geometry, vegetation.
contradictionsstring[]Evidence that argues AGAINST it. A non-empty array is not a failure — it is the reason a reviewer should look closer before acting.
candidatesobject[]Alternative locations considered, each with lat, lng, label, confidence (0–100), supports and contradictions.
"forensic": {
  "precision_tier": "block",
  "verification_status": "partially_verified",
  "supports": [
    "Street sign reads 'Rue de Créqui'",
    "Haussmann-era facade with 6th-arrondissement cornice detail"
  ],
  "contradictions": [
    "Bollard style is more common in Lyon 3e than 6e"
  ],
  "candidates": [
    {
      "label": "Rue Vendôme, Lyon 6e",
      "lat": 45.7688,
      "lng": 4.8441,
      "confidence": 62,
      "supports": ["Matching tree spacing"],
      "contradictions": ["Street sign does not match"]
    }
  ]
}

Confidence is reported as the model assesses it and is not inflated when evidence is thin. A low score with populated contradictions is the system telling you it is not certain, which is the signal you want in a claim, a dispute, or a moderation decision.

Errors

401Missing or invalid API key.
402Insufficient credits for the requested depth.
409The Idempotency-Key is still processing or was already used with a different request payload.
422No image_b64 or image_url provided, or image_url could not be fetched.
422Returns code: "invalid_effort" for an unknown effort value, or code: "effort_exceeds_depth" when the requested effort is above what that depth runs. The latter carries max_effort.
404The batch_id does not exist or is bound to a different API key.
422Returns code: "content_blocked" when an image fails content-safety screening. Screening runs before credits are reserved, so a blocked image is never charged.
429Rate limit exceeded — retry after retry_after seconds.
422Returns code: "invalid_image_b64" when image_b64 is not decodable base64, or carries a data: URL prefix. Send raw base64.
422Returns code: "invalid_scope" when the optional scope field cannot be parsed as a city scope. Omit scope entirely for a worldwide analysis. This also covers scope.captured_at: it must begin with a real calendar date, and a date the calendar does not have (2026-02-31) is rejected rather than rolled forward.
403Returns code: "depth_not_permitted" when the key requests a depth above the cap set on it. The response carries max_depth so a caller can retry at a depth the key allows. Checked before the async branch, so an over-depth submit fails at request time rather than returning 202 and dying inside the job.
422Returns code: "webhook_required_for_async" when async: true is sent by a key whose account has analysis history disabled. With retention off there is nothing to poll, so a webhook is the only way the result can reach you — register one or send the request synchronously.
402Returns code: "prepaid_credits_exhausted" when an enterprise prepaid allocation is spent. Contact Oceanir rather than retrying.
409Returns code: "idempotency_in_progress" when the same Idempotency-Key is still being processed. Wait and retry the same key.
502Analysis failed upstream, code: "analysis_failed". Retry, or lower the depth. Not charged.
503Inference backend unavailable. Transient — retry with backoff. Not charged.
504Analysis timed out before completion. Returns code: "analysis_timeout" and retryable: true. Credits are refunded automatically — safe to retry, or use a lower depth.