API Versioning
Manage API version changes gracefully and maintain backward compatibility. Learn about Omise's versioning strategy, how to specify versions, and best practices for upgrades.
Overviewโ
Omise uses date-based API versioning to introduce improvements without breaking existing integrations. Each version is named by its release date (YYYY-MM-DD format). You can control which API version your integration uses to ensure stability and plan upgrades on your schedule.
- Current Version:
2019-05-29 - Use
Omise-Versionheader to specify version - No header = account's default version
- Versions never change - your integration stays stable
- Plan upgrades when new features are needed
Current API Versionโ
Latest Version: 2019-05-29โ
Released: May 29, 2019
This is the current stable version of the Omise API. All new integrations should use this version.
curl https://api.omise.co/charges \
-u skey_test_...: \
-H "Omise-Version: 2019-05-29"
How Versioning Worksโ
Version Formatโ
Omise API versions use date-based naming:
YYYY-MM-DD
Examples:
2019-05-29- May 29, 2019 release2017-11-02- November 2, 2017 release2015-11-17- November 17, 2015 release
Specifying API Versionโ
You can specify the API version in two ways:
1. Per-Request Header (Recommended)โ
Use the Omise-Version header:
curl https://api.omise.co/charges \
-u skey_test_...: \
-H "Omise-Version: 2019-05-29" \
-X POST \
-d "amount=100000" \
-d "currency=thb"
Benefits:
- โ Explicit version control per request
- โ Easy to test new versions
- โ Can use different versions for different operations
- โ Overrides account default
2. Account Default Versionโ
Set a default version in your Dashboard:
- Log in to Omise Dashboard
- Go to Settings โ API Version
- Select version
- Save
All requests without Omise-Version header use this version.
Version Behaviorโ
How Versions Workโ
- Versions are immutable - A version's behavior never changes
- New versions introduce changes - Breaking changes only in new versions
- You control upgrades - Explicitly opt-in to new versions
- Old versions supported - Legacy versions remain available
Example Timelineโ
2015-11-17 โ Your integration built
โ
2017-11-02 โ New version released
โ (Your integration still uses 2015-11-17)
โ
2019-05-29 โ New version released
โ (Your integration still uses 2015-11-17)
โ
Today โ You upgrade to 2019-05-29
โ (Opt-in when ready)
Specifying Version in Codeโ
Rubyโ
require 'omise'
Omise.api_key = ENV['OMISE_SECRET_KEY']
Omise.api_version = '2019-05-29'
# All requests use specified version
charge = Omise::Charge.create({
amount: 100000,
currency: 'thb',
card: token
})
Pythonโ
import omise
omise.api_secret = os.environ['OMISE_SECRET_KEY']
omise.api_version = '2019-05-29'
# All requests use specified version
charge = omise.Charge.create(
amount=100000,
currency='thb',
card=token
)
PHPโ
<?php
require_once 'vendor/autoload.php';
define('OMISE_SECRET_KEY', getenv('OMISE_SECRET_KEY'));
define('OMISE_API_VERSION', '2019-05-29');
OmiseCharge::create([
'amount' => 100000,
'currency' => 'thb',
'card' => $token
]);
Node.jsโ
const omise = require('omise')({
secretKey: process.env.OMISE_SECRET_KEY,
omiseVersion: '2019-05-29'
});
// All requests use specified version
const charge = await omise.charges.create({
amount: 100000,
currency: 'thb',
card: token
});
Goโ
package main
import (
"github.com/omise/omise-go"
"github.com/omise/omise-go/operations"
)
func main() {
client, _ := omise.NewClient(
os.Getenv("OMISE_PUBLIC_KEY"),
os.Getenv("OMISE_SECRET_KEY"),
)
// Set API version
client.APIVersion = "2019-05-29"
charge, _ := client.CreateCharge(&operations.CreateCharge{
Amount: 100000,
Currency: "thb",
Card: token,
})
}
cURLโ
# Specify version in header
curl https://api.omise.co/charges \
-u skey_test_...: \
-H "Omise-Version: 2019-05-29" \
-X POST \
-d "amount=100000" \
-d "currency=thb" \
-d "card=tokn_test_..."
Breaking vs Non-Breaking Changesโ
Breaking Changesโ
Breaking changes are only introduced in new API versions:
Examples:
- Removing API endpoints
- Removing response fields
- Changing response field types
- Changing required parameters
- Changing error codes
- Modifying behavior that affects existing flows
How Omise handles them:
- โ Released as new version (new date)
- โ Old version continues to work
- โ You opt-in when ready
- โ Migration guide provided
Non-Breaking Changesโ
Non-breaking changes may be added to all versions:
Examples:
- Adding new API endpoints
- Adding new response fields
- Adding new optional parameters
- Adding new error codes
- Adding new event types
- Improving performance
How to handle:
- โ Ignore unknown fields in responses
- โ Don't rely on field order
- โ Handle unexpected values gracefully
- โ Test with production-like data
Build your integration to handle new fields gracefully:
// โ
Good - Ignores unknown fields
const { id, amount, status } = charge;
// โ Bad - Breaks if new fields added
const charge = { id, amount, status }; // Assumes only these fields
Version Historyโ
2019-05-29 (Current)โ
Released: May 29, 2019
Changes:
- Enhanced source object structure
- Improved error responses
- Updated charge flow handling
- Better webhook event payloads
- Refined payment method objects
Migration from 2017-11-02:
- Source objects have additional fields
- Some charge status transitions refined
- Event payloads include more context
- Test all payment flows after upgrading
2017-11-02โ
Released: November 2, 2017
Changes:
- Introduced Sources API for alternative payments
- Enhanced customer object
- Improved dispute handling
- Added schedule objects
- Updated transfer logic
Migration from 2015-11-17:
- Use sources instead of offsite for alternative payments
- Update customer handling code
- Review dispute webhooks
- Test scheduled operations
2015-11-17โ
Released: November 17, 2015
Legacy version - Still supported but missing newer features:
- No sources API (uses older offsite method)
- Limited payment methods
- Older event structures
Recommendation: Upgrade to 2019-05-29 for best experience
Migration Guideโ
Planning an Upgradeโ
- Review changelog for new version
- Identify breaking changes affecting your integration
- Test in test mode with new version
- Update code to handle changes
- Test thoroughly before production
- Deploy to production during low-traffic period
- Monitor for issues
- Update account default when stable
Testing New Versionโ
# Test new version in parallel with current version
def create_charge_v2019(params)
charge = Omise::Charge.create(
params,
{ 'Omise-Version' => '2019-05-29' }
)
# Log differences
logger.info("New version charge: #{charge.to_json}")
charge
end
def create_charge_current(params)
charge = Omise::Charge.create(
params,
{ 'Omise-Version' => '2017-11-02' }
)
logger.info("Current version charge: #{charge.to_json}")
charge
end
# Compare results
new_charge = create_charge_v2019(charge_params)
old_charge = create_charge_current(charge_params)
compare_charges(new_charge, old_charge)
Gradual Migrationโ
// Use feature flags for gradual rollout
const useNewAPIVersion = featureFlags.isEnabled('api-version-2019');
const omise = require('omise')({
secretKey: process.env.OMISE_SECRET_KEY,
omiseVersion: useNewAPIVersion ? '2019-05-29' : '2017-11-02'
});
// Monitor both versions
if (useNewAPIVersion) {
analytics.track('api_version_2019_used');
}
Version Detectionโ
# Detect which version was used in response
def get_api_version_from_response(response_headers):
return response_headers.get('Omise-Version')
# Example
response = omise.Charge.retrieve('chrg_test_...')
version = get_api_version_from_response(response.headers)
print(f"Response from API version: {version}")
Deprecation Policyโ
How Deprecation Worksโ
- New version released with changes
- Old version continues working (no immediate impact)
- Deprecation announced via:
- Email notifications
- Dashboard notifications
- API changelog
- Developer documentation
- Migration period (typically 12+ months)
- End-of-life warnings (6 months before sunset)
- Version sunset (old version stops working)
Deprecation Timeline Exampleโ
Month 0: New version released (2019-05-29)
Old version (2017-11-02) still works
Month 1: Deprecation announced
Migration guide published
Month 6: Reminder notifications sent
Month 12: Final warning (6 months to sunset)
Month 18: Version 2017-11-02 sunset
Requests without version header use 2019-05-29
Checking for Deprecationsโ
# Check response headers for deprecation warnings
curl -i https://api.omise.co/charges \
-u skey_test_...: \
-H "Omise-Version: 2017-11-02"
# Look for deprecation header
# Omise-Deprecated: true
# Omise-Sunset: 2025-12-31
# Omise-Recommended-Version: 2019-05-29
Best Practicesโ
1. Pin API Version Explicitlyโ
# โ
Good - Explicit version
Omise.api_version = '2019-05-29'
# โ Bad - Relies on account default
Omise.api_version = nil # Uses account default
Why:
- โ Prevents unexpected changes
- โ Makes version clear in code
- โ Easier to test upgrades
- โ Consistent across environments
2. Use Environment Variablesโ
// โ
Good - Version in config
const omise = require('omise')({
secretKey: process.env.OMISE_SECRET_KEY,
omiseVersion: process.env.OMISE_API_VERSION || '2019-05-29'
});
Benefits:
- โ Easy to change without code deploy
- โ Different versions per environment
- โ Centralized configuration
3. Test Version Upgrades Thoroughlyโ
# Test suite for version upgrade
class TestAPIVersion2019(unittest.TestCase):
def setUp(self):
omise.api_version = '2019-05-29'
def test_charge_creation(self):
charge = omise.Charge.create(
amount=100000,
currency='thb',
card=token
)
self.assertEqual(charge.amount, 100000)
def test_source_creation(self):
source = omise.Source.create(
type='promptpay',
amount=100000,
currency='thb'
)
self.assertIsNotNone(source.scannable_code)
def test_customer_with_card(self):
customer = omise.Customer.create(
email='test@example.com',
card=token
)
self.assertIsNotNone(customer.default_card)
4. Handle Unknown Fields Gracefullyโ
// โ
Good - Defensive parsing
function parseCharge(chargeData) {
return {
id: chargeData.id,
amount: chargeData.amount,
currency: chargeData.currency,
status: chargeData.status,
// Store unknown fields for future compatibility
_raw: chargeData
};
}
// โ Bad - Assumes fixed structure
function parseChargeBad(chargeData) {
const { id, amount, currency, status } = chargeData;
return { id, amount, currency, status };
// Breaks if structure changes
}
5. Monitor API Version Usageโ
# Log API version for monitoring
class OmiseLogger
def self.log_request(endpoint, version)
Rails.logger.info({
event: 'omise_api_request',
endpoint: endpoint,
api_version: version,
timestamp: Time.now.iso8601
}.to_json)
end
end
# Use in requests
OmiseLogger.log_request('/charges', '2019-05-29')
charge = Omise::Charge.create(params)
6. Document Version in Codeโ
<?php
/**
* Omise API Integration
*
* API Version: 2019-05-29
* Last Updated: 2025-01-15
* Migration Guide: https://docs.omise.co/api-versioning
*
* IMPORTANT: When upgrading API version:
* 1. Review changelog
* 2. Test all payment flows
* 3. Check webhook handlers
* 4. Update this comment
*/
class OmisePayment {
const API_VERSION = '2019-05-29';
public function createCharge($params) {
return OmiseCharge::create($params, [
'Omise-Version' => self::API_VERSION
]);
}
}
7. Version in CI/CDโ
# .env.example
OMISE_API_VERSION=2019-05-29
# docker-compose.yml
version: '3.8'
services:
app:
environment:
- OMISE_API_VERSION=${OMISE_API_VERSION}
# GitHub Actions
- name: Run tests
env:
OMISE_API_VERSION: 2019-05-29
run: npm test
Version Upgrade Checklistโ
Before upgrading to a new API version:
Pre-Upgradeโ
- Review complete changelog for new version
- Identify all breaking changes
- Check if your code uses deprecated features
- Review migration guide
- Update dependencies (SDK libraries)
- Plan rollback strategy
Testingโ
- Test in test mode with new version header
- Test all payment flows (cards, alternative payments)
- Test customer creation and management
- Test refund operations
- Test transfer operations
- Verify webhook payload handling
- Test error handling
- Load test critical paths
- Compare responses with old version
Deploymentโ
- Update API version in code
- Deploy to staging environment
- Run smoke tests
- Monitor error rates
- Deploy to production (low-traffic period)
- Monitor dashboards
- Check webhook deliveries
- Verify payment success rates
Post-Upgradeโ
- Monitor for 24-48 hours
- Review logs for anomalies
- Check error rates
- Verify reporting accuracy
- Update documentation
- Update account default version (optional)
- Document any code changes
- Train team on changes
Troubleshooting Version Issuesโ
Version Mismatch Errorsโ
Problem: Unexpected behavior or errors after version change
Solution:
# Check which version is being used
def debug_api_version
# Make a test request
response = Omise::Account.retrieve
# Check response headers
version = response.http_headers['Omise-Version']
puts "API Version used: #{version}"
# Check client configuration
puts "Client version: #{Omise.api_version}"
# Check account default
puts "Check Dashboard Settings โ API Version for account default"
end
Response Structure Differencesโ
Problem: Fields missing or different type
Solution:
# Compare responses across versions
def compare_versions(operation_fn):
# Version 1
omise.api_version = '2017-11-02'
response_v1 = operation_fn()
# Version 2
omise.api_version = '2019-05-29'
response_v2 = operation_fn()
# Compare
print("Version 2017-11-02:")
print(json.dumps(response_v1, indent=2))
print("\nVersion 2019-05-29:")
print(json.dumps(response_v2, indent=2))
# Find differences
diff = deepdiff.DeepDiff(response_v1, response_v2)
print("\nDifferences:")
print(json.dumps(diff, indent=2))
# Usage
compare_versions(lambda: omise.Charge.retrieve('chrg_test_...'))
SDK Version Compatibilityโ
Problem: SDK doesn't support new API version
Solution:
# Check SDK version
# Ruby
gem list omise
# Python
pip show omise
# Node.js
npm list omise
# Update to latest
# Ruby
gem update omise
# Python
pip install --upgrade omise
# Node.js
npm update omise
FAQโ
What happens if I don't specify a version?
Your requests will use your account's default API version (set in Dashboard). This can lead to inconsistent behavior if the default changes. Always specify the version explicitly in your code.
Can I use different versions for different requests?
Yes! You can specify different versions per request using the Omise-Version header. This is useful during migration to test new version behavior alongside existing integration.
# Request 1 - Old version
curl -H "Omise-Version: 2017-11-02" ...
# Request 2 - New version
curl -H "Omise-Version: 2019-05-29" ...
How often are new versions released?
Omise releases new API versions infrequently - typically when significant improvements or necessary breaking changes are made. Versions are supported for years after release. The current version (2019-05-29) has been stable since 2019.
Do I need to upgrade immediately when a new version is released?
No. Your current version continues to work. You can upgrade on your own schedule:
- Upgrade for new features
- Upgrade before old version sunset
- Upgrade during planned maintenance windows
You typically have 18+ months from deprecation announcement to upgrade.
Will my integration break if I don't upgrade?
Not immediately. Your integration will continue working on its current version. However:
- You won't get new features
- Eventually old versions are sunset (with 18+ months notice)
- Security improvements may require upgrades
Plan regular version reviews (every 6-12 months).
How do I know when my version is deprecated?
Omise notifies you via:
- Email to account owner
- Dashboard notifications
- Response headers (
Omise-Deprecated: true) - API changelog
- Developer documentation
Set up monitoring for deprecation headers in your logs.
Can I test a new version without affecting production?
Yes! Use the Omise-Version header:
- Keep production on current version (account default)
- Test new version in staging with header
- Run parallel tests comparing versions
- Upgrade production when ready
# Production (uses account default)
Omise::Charge.create(params)
# Staging (tests new version)
Omise::Charge.create(
params,
{ 'Omise-Version' => '2019-05-29' }
)
Quick Referenceโ
Current Versionโ
2019-05-29
Specify Versionโ
# In header
curl -H "Omise-Version: 2019-05-29" ...
# In Ruby
Omise.api_version = '2019-05-29'
# In Python
omise.api_version = '2019-05-29'
# In Node.js
omise = require('omise')({ omiseVersion: '2019-05-29' })
# In PHP
define('OMISE_API_VERSION', '2019-05-29');
# In Go
client.APIVersion = "2019-05-29"
Version Formatโ
YYYY-MM-DD (e.g., 2019-05-29)
Breaking Changesโ
- Only in new versions
- Old versions stay stable
- You control upgrade timing
- Migration guide provided
Non-Breaking Changesโ
- May be added to all versions
- New fields, endpoints, features
- Handle unknown fields gracefully
- Build forward-compatible code
Related Resourcesโ
Next: Learn about Rate Limiting to stay within API limits and handle rate limit errors.