Skip to main content

Dispense an authorization at the pharmacy

This guide walks a pharmacy through redeeming an authorization or electronic-prescription code at the point of sale. The dispensation endpoints work the same for both code types — Osigu tells them apart internally.

If you haven't already, skim Dispensing to understand why the flow is two-phase (start + complete).

Prerequisites

  • Access to an OAuth token with dispensing:write scope.
  • The beneficiary is physically at the counter — some sponsors require OTP or biometric.
  • Either an authorization code (from a previous pre-authorization) or an electronic prescription code.

1. Start the dispensation

curl -X POST "https://sandbox.osigu.com/dispensing/v1/dispensations" \
-H "Authorization: Bearer $TOKEN" \
-H "Content-Type: application/json" \
-d '{
"code": "AUTH-2026-001234",
"beneficiary_id": "bnf_01HW8GQ..."
}'

Response (201):

{
"dispensation_id": "dsp_01HXDN...",
"status": "STARTED",
"code_type": "AUTHORIZATION",
"products": [
{ "product_code": "MED-042", "quantity": 30, "unit_price": 12.50 }
],
"verification_required": "OTP"
}

Two things to note:

  • code_type tells you whether this came from a pre-authorization or an electronic prescription — the UI may differ.
  • verification_required is null, "OTP", or "BIOMETRIC". If not null, run step 2. If null, jump to step 4.

2. Verification: OTP or biometric

OTP

Trigger the sponsor to send an OTP to the beneficiary:

curl -X POST "https://sandbox.osigu.com/v1/otp/send" \
-H "Authorization: Bearer $TOKEN" \
-H "Content-Type: application/json" \
-d '{
"beneficiary_id": "bnf_...",
"sponsor_slug": "sponsor-sandbox",
"channel": "SMS"
}'

Ask the beneficiary for the code, then:

curl -X POST "https://sandbox.osigu.com/v1/otp/validate" \
-H "Authorization: Bearer $TOKEN" \
-H "Content-Type: application/json" \
-d '{"otp_id": "otp_...", "code": "482913"}'

Persist the returned otp_verification_token.

Biometric

The pharmacy captures a fingerprint or facial reading with its onsite device and sends it as Base64 to the biometric endpoint. The exact endpoint depends on the sponsor's biometric provider — check the sponsor configuration.

Poll getDispensationVerificationStatus until it flips to VERIFIED before you complete.

3. Swap products (optional)

If the sponsor allows substitution and you're dispensing a different presentation, patch the products:

curl -X PUT "https://sandbox.osigu.com/dispensing/v1/dispensations/dsp_.../products" \
-H "Authorization: Bearer $TOKEN" \
-H "Content-Type: application/json" \
-d '{
"products": [
{ "product_code": "MED-042-ALT", "quantity": 30 }
]
}'

If the substitution violates the sponsor's rules you get 422 — the original product list stays.

4. Complete the dispensation

curl -X POST "https://sandbox.osigu.com/dispensing/v1/dispensations/dsp_.../complete" \
-H "Authorization: Bearer $TOKEN" \
-H "Content-Type: application/json" \
-d '{
"otp_verification_token": "otvt_..."
}'

(Include otp_verification_token only if step 2 ran.)

Response (200):

{
"dispensation_id": "dsp_01HXDN...",
"status": "DISPENSED",
"dispensed_at": "2026-06-25T15:04:00Z"
}

The authorization or prescription is now redeemed. Osigu emits a dispensing.completed webhook to the provider (and, if configured, to the sponsor).

5. Void if the customer walks away

If the beneficiary changes their mind before completion:

curl -X POST "https://sandbox.osigu.com/dispensing/v1/dispensations/dsp_.../void" \
-H "Authorization: Bearer $TOKEN" \
-H "Content-Type: application/json" \
-d '{"reason": "Beneficiary declined"}'

Void isn't allowed once status = DISPENSED. Coordinate a return with the sponsor if you need to reverse a completed dispensation.

Troubleshooting

SymptomFix
404 on startDispensationWrong code, or code belongs to a sponsor your provider isn't affiliated with.
409 on startCode already dispensed, or another STARTED dispensation exists for the same code.
PENDING_VERIFICATION never flipsThe beneficiary hasn't entered the OTP, or the biometric reading failed. Time out after ~2 minutes and offer them a retry.
422 on updateDispensationProductsSubstitution not allowed for this sponsor, or the alternative isn't in your provider products.