Pepvote Support Center

Cast Public Ballot

POST
/public/voting-events/{idOrCode}/ballot/cast

Casts one ballot. Elections need voterKey; polls need visitorId. On a pay-to-vote poll the first call returns 402 with a checkout; call again with only paymentAttemptId after the payer returns to finish the cast.

Authorization

bearerAuth
AuthorizationBearer <token>

A key in the form pepvote_api_ followed by 32 hexadecimal characters.

In: header

Header Parameters

Idempotency-Keystring

Optional retry key. First successful response is stored for 24 hours.

  • Length: up to 255 characters
User-Agentstringrequired

Name and version of the calling integration. Required on every request.

Path Parameters

idOrCodestringrequired

Voting event ID or code.

Request Body

application/json

TypeScript Definitions

Use the request body type in TypeScript.

paymentAttemptIdstring

Second call only. The attempt returned in the 402. The ballot is stored on the attempt, so every other field is ignored.

votesarray<object>

One entry per selected, scored, allocated, or ranked candidate. Required on the first call.

  • Items: 1 to 200 items
voterKeystring

Voter key from the email. Required for elections.

  • Length: up to 200 characters
visitorIdstring

Required for polls. vi_ followed by 16 to 128 hex characters.

  • Length: up to 200 characters
  • Pattern: ^vi_[0-9a-fA-F]{16,128}$
voterIdstring

External voter ID for polls that require one.

  • Length: up to 200 characters
namestring

Voter name, stored when the poll saves voter info.

  • Length: up to 200 characters
emailstring

Voter email. Required by Paystack checkouts.

  • Length: up to 320 characters
countryCodestring

Two-letter ISO country code of the voter, for the insights geography breakdown.

  • Length: exactly 2 characters
returnUrlstring

Absolute http(s) URL the payer lands on after a provider-hosted checkout, with paymentAttemptId appended. Required when payments.provider is stripe.

  • Length: up to 2048 characters
  • Format: uri
cancelUrlstring

Absolute http(s) URL the payer lands on after cancelling the checkout, with paymentAttemptId appended.

  • Length: up to 2048 characters
  • Format: uri

Response Body

application/json

application/json

application/json

curl -X POST "https://example.com/public/voting-events/string/ballot/cast" \  -H "User-Agent: my-app/1.0" \  -H "Content-Type: application/json" \  -d '{}'
{
  "data": {
    "confirmationCode": "string",
    "votesCount": 0
  }
}
{
  "data": {
    "paymentRequired": true,
    "paymentAttemptId": "string",
    "amount": 0,
    "currency": "string",
    "provider": "stripe",
    "stripe": {
      "checkoutUrl": "http://example.com",
      "checkoutSessionId": "string"
    },
    "next": "string"
  }
}
{
  "error": {
    "code": "bad_request",
    "message": "string",
    "details": {
      "field": "string",
      "parameter": "string",
      "limit": 0,
      "retryAfterSeconds": 0,
      "feature": "string",
      "plan": "string"
    }
  }
}
Was this helpful?

Last updated September 6, 2026