Endpoints
Offers
Upload offer records to the Cobi Data API
Offers
curl --request POST \
--url https://api.example.com/v1/data/offers \
--header 'Content-Type: application/json' \
--data '
{
"records": [
{
"offer_id": {},
"shop_id": {},
"name": "<string>",
"type": "<string>",
"value": {},
"region": "<string>",
"allowed_from": {},
"allowed_to": {},
"allowed_branches": "<string>",
"allowed_days": "<string>",
"created": {},
"updated": {},
"is_deleted": true,
"is_enabled": true
}
]
}
'import requests
url = "https://api.example.com/v1/data/offers"
payload = { "records": [
{
"offer_id": {},
"shop_id": {},
"name": "<string>",
"type": "<string>",
"value": {},
"region": "<string>",
"allowed_from": {},
"allowed_to": {},
"allowed_branches": "<string>",
"allowed_days": "<string>",
"created": {},
"updated": {},
"is_deleted": True,
"is_enabled": True
}
] }
headers = {"Content-Type": "application/json"}
response = requests.post(url, json=payload, headers=headers)
print(response.text)const options = {
method: 'POST',
headers: {'Content-Type': 'application/json'},
body: JSON.stringify({
records: [
{
offer_id: {},
shop_id: {},
name: '<string>',
type: '<string>',
value: {},
region: '<string>',
allowed_from: {},
allowed_to: {},
allowed_branches: '<string>',
allowed_days: '<string>',
created: {},
updated: {},
is_deleted: true,
is_enabled: true
}
]
})
};
fetch('https://api.example.com/v1/data/offers', options)
.then(res => res.json())
.then(res => console.log(res))
.catch(err => console.error(err));<?php
$curl = curl_init();
curl_setopt_array($curl, [
CURLOPT_URL => "https://api.example.com/v1/data/offers",
CURLOPT_RETURNTRANSFER => true,
CURLOPT_ENCODING => "",
CURLOPT_MAXREDIRS => 10,
CURLOPT_TIMEOUT => 30,
CURLOPT_HTTP_VERSION => CURL_HTTP_VERSION_1_1,
CURLOPT_CUSTOMREQUEST => "POST",
CURLOPT_POSTFIELDS => json_encode([
'records' => [
[
'offer_id' => [
],
'shop_id' => [
],
'name' => '<string>',
'type' => '<string>',
'value' => [
],
'region' => '<string>',
'allowed_from' => [
],
'allowed_to' => [
],
'allowed_branches' => '<string>',
'allowed_days' => '<string>',
'created' => [
],
'updated' => [
],
'is_deleted' => true,
'is_enabled' => true
]
]
]),
CURLOPT_HTTPHEADER => [
"Content-Type: application/json"
],
]);
$response = curl_exec($curl);
$err = curl_error($curl);
curl_close($curl);
if ($err) {
echo "cURL Error #:" . $err;
} else {
echo $response;
}package main
import (
"fmt"
"strings"
"net/http"
"io"
)
func main() {
url := "https://api.example.com/v1/data/offers"
payload := strings.NewReader("{\n \"records\": [\n {\n \"offer_id\": {},\n \"shop_id\": {},\n \"name\": \"<string>\",\n \"type\": \"<string>\",\n \"value\": {},\n \"region\": \"<string>\",\n \"allowed_from\": {},\n \"allowed_to\": {},\n \"allowed_branches\": \"<string>\",\n \"allowed_days\": \"<string>\",\n \"created\": {},\n \"updated\": {},\n \"is_deleted\": true,\n \"is_enabled\": true\n }\n ]\n}")
req, _ := http.NewRequest("POST", url, payload)
req.Header.Add("Content-Type", "application/json")
res, _ := http.DefaultClient.Do(req)
defer res.Body.Close()
body, _ := io.ReadAll(res.Body)
fmt.Println(string(body))
}HttpResponse<String> response = Unirest.post("https://api.example.com/v1/data/offers")
.header("Content-Type", "application/json")
.body("{\n \"records\": [\n {\n \"offer_id\": {},\n \"shop_id\": {},\n \"name\": \"<string>\",\n \"type\": \"<string>\",\n \"value\": {},\n \"region\": \"<string>\",\n \"allowed_from\": {},\n \"allowed_to\": {},\n \"allowed_branches\": \"<string>\",\n \"allowed_days\": \"<string>\",\n \"created\": {},\n \"updated\": {},\n \"is_deleted\": true,\n \"is_enabled\": true\n }\n ]\n}")
.asString();require 'uri'
require 'net/http'
url = URI("https://api.example.com/v1/data/offers")
http = Net::HTTP.new(url.host, url.port)
http.use_ssl = true
request = Net::HTTP::Post.new(url)
request["Content-Type"] = 'application/json'
request.body = "{\n \"records\": [\n {\n \"offer_id\": {},\n \"shop_id\": {},\n \"name\": \"<string>\",\n \"type\": \"<string>\",\n \"value\": {},\n \"region\": \"<string>\",\n \"allowed_from\": {},\n \"allowed_to\": {},\n \"allowed_branches\": \"<string>\",\n \"allowed_days\": \"<string>\",\n \"created\": {},\n \"updated\": {},\n \"is_deleted\": true,\n \"is_enabled\": true\n }\n ]\n}"
response = http.request(request)
puts response.read_bodyImportant: Offer records have a dependency on shops. The system validates
the
shop_id field against existing records in the database. You should
upload shops before uploading offers to ensure proper data validation.Authentication Required
This endpoint requires API key authentication via Bearer token in the Authorization header.Authorization: Bearer YOUR_API_KEY
Content-Type: application/json
About the Data API
This endpoint is part of the Cobi Data API (/v1/data/:type), which provides a consistent interface for uploading different types of structured data.
Request Body
array
required
An array of offer records (up to 5000)
Show Offer Record
Show Offer Record
string (UUID)
required
Unique identifier for the offer
string (UUID)
required
ID of the shop offering the discount (must reference an existing shop)
string
required
Name of the offer
string
required
Type of offer (e.g., “percentage”, “fixed”)
number (float)
required
Value of the offer (must be a positive number)
string
required
Geographic region (2-letter country code, e.g., “CA” for Canada)
string (date-time)
Start date and time of the offer
string (date-time)
End date and time of the offer
string
Comma-separated list of branch IDs where the offer is valid
string
Comma-separated list of days when the offer is valid
string (date-time)
Timestamp when the record was created
string (date-time)
Timestamp when the record was last updated
boolean
Flag indicating if the record is marked as deleted
boolean
Flag indicating if the offer is currently enabled
Response
The API returns a JSON response with the following fields:{
"request_id": "string", // Unique ID for the overall request
"type": "offers", // Type of data being processed
"batches": [
{
"batch": 1, // Sequential batch number
"status": 200, // HTTP-like status code (200, 207, 400, 500)
"data": {
"status": "success", // "success", "partial", or "error"
"type": "offers", // Matches the top-level type
"message": "Records uploaded successfully", // Summary message
"request_id": "string",
"batch_id": "string",
"error": "" // Optional — empty or null on success; contains error details otherwise
}
}
]
}
| Field | Type | Description |
|---|---|---|
request_id | string | Unique ID for the overall request |
type | string | Type of data being processed (e.g., “offers”) |
batches | array | Array of batch results |
batches[].batch | int | Sequential batch number |
batches[].status | int | HTTP-like status code (200, 207, 400, 500) |
batches[].data | object | Batch result details |
batches[].data.status | string | ”success”, “partial”, or “error” |
batches[].data.type | string | Matches the top-level type |
batches[].data.message | string | Summary message of the batch result |
batches[].data.request_id | string | Unique request ID for the batch |
batches[].data.batch_id | string | Unique batch ID |
batches[].data.error | string | Error details (empty or null on success) |
Error Codes
| Status Code | Description | data.status value |
|---|---|---|
| 200 | All records processed successfully | success |
| 207 | Some records failed, others succeeded | partial |
| 400 | Validation or dependency error | error |
| 500 | Internal or unexpected server error | error |
| 401 | Unauthorized - Invalid or missing API key | error |
Example
curl -X POST https://api.hellocobi.com/v1/data/offers \
-H "Authorization: Bearer YOUR_API_KEY" \
-H "Content-Type: application/json" \
-d '{
"records": [
{
"offer_id": "550e8400-e29b-41d4-a716-446655440000",
"shop_id": "550e8400-e29b-41d4-a716-446655440001",
"name": "Student Discount",
"type": "percentage",
"value": 10.0,
"region": "CA",
"allowed_from": "2024-01-01T00:00:00Z",
"allowed_to": "2024-12-31T23:59:59Z",
"allowed_branches": "branch1,branch2",
"allowed_days": "monday,tuesday,wednesday",
"is_enabled": true
}
]
}'
Best Practices
- Upload Order: Upload shops before offers to ensure references exist
- Batch Size: Upload up to 5000 records at a time for optimal performance
- Data Validation: Ensure all required fields are present and properly formatted
- Error Handling: Implement proper error handling for failed requests
- Rate Limiting: Be mindful of API rate limits
Was this page helpful?
⌘I